diff --git a/.hgtags b/.hgtags
index f05b8bd17add39be304a63331a813a260edbdbf5..0cc10b010006185fa307e139c121700d4265cff7 100755
--- a/.hgtags
+++ b/.hgtags
@@ -507,3 +507,4 @@ d07f76c5b9860fb87924d00ca729f7d4532534d6 3.7.29-release
 3f61ed662347dc7c6941b8266e72746a66d90e2a 3.8.1-release
 3a62616f3dd8bd512fcdfd29ef033b2505b11213 3.8.2-release
 60572f718879f786f6bc8b5c9373ebebf4693078 3.8.3-release
+27e3cf444c4cc645884960a61325a9ee0e9a2d0f 3.8.4-release
diff --git a/BuildParams b/BuildParams
index aeea3b1246868b59c1a58f3b4d3ff6b6347b79c8..7aff447ddaec679146a99d8e76e8d8e354c7afc4 100755
--- a/BuildParams
+++ b/BuildParams
@@ -4,7 +4,7 @@
 #  https://wiki.secondlife.com/wiki/Automated_Build_System
 
 
-# Global setting for now...
+# Global setting for now....
 Darwin.symbolfiles = "newview/Release/secondlife-symbols-darwin.tar.bz2"
 CYGWIN.symbolfiles = "newview/Release/secondlife-symbols-windows.tar.bz2"
 Linux.symbolfiles = "newview/secondlife-symbols-linux.tar.bz2"
diff --git a/autobuild.xml b/autobuild.xml
index 52d750f64d66a074096d58a75d02f2c428a3ac67..7488b816ec6d55280cef1521a66fb991691f3808 100755
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -87,60 +87,6 @@
         <key>version</key>
         <string>1.4.5.297252</string>
       </map>
-      <key>ares</key>
-      <map>
-        <key>copyright</key>
-        <string>Copyright 1998 by the Massachusetts Institute of Technology.</string>
-        <key>description</key>
-        <string>C-ares, an asynchronous resolver library.</string>
-        <key>license</key>
-        <string>c-ares</string>
-        <key>license_file</key>
-        <string>LICENSES/c-ares.txt</string>
-        <key>name</key>
-        <string>ares</string>
-        <key>platforms</key>
-        <map>
-          <key>darwin</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>637b4996f703f3e5bf835d847fc4cb81</string>
-              <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/ares_3p-update-ares/rev/295506/arch/Darwin/installer/ares-1.10.0.295506-darwin-295506.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>darwin</string>
-          </map>
-          <key>linux</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>7771d3653a0daf22d35bf96055d02d9a</string>
-              <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/ares_3p-update-ares/rev/295506/arch/Linux/installer/ares-1.10.0.295506-linux-295506.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>linux</string>
-          </map>
-          <key>windows</key>
-          <map>
-            <key>archive</key>
-            <map>
-              <key>hash</key>
-              <string>f044de05e704d3f3fb6934adf42447c2</string>
-              <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/ares_3p-update-ares/rev/295506/arch/CYGWIN/installer/ares-1.10.0.295506-windows-295506.tar.bz2</string>
-            </map>
-            <key>name</key>
-            <string>windows</string>
-          </map>
-        </map>
-        <key>version</key>
-        <string>1.10.0.295506</string>
-      </map>
       <key>boost</key>
       <map>
         <key>copyright</key>
@@ -266,9 +212,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d1c5125650a339a5209f429c70f4d395</string>
+              <string>89db4a1aa22599cf377ae49630b7b5b1</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/297172/arch/Darwin/installer/curl-7.38.0.297172-darwin-297172.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/301717/arch/Darwin/installer/curl-7.42.1.301717-darwin-301717.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -278,9 +224,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ee6c089ee193e551040d610befc5d1c1</string>
+              <string>de9e0c855ff6ee30c9e027a70bbef032</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/297172/arch/Linux/installer/curl-7.38.0.297172-linux-297172.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/301717/arch/Linux/installer/curl-7.42.1.301717-linux-301717.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -290,16 +236,16 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>fdeca7cbc074a88d2701d74a31d21bd8</string>
+              <string>98d15713de8c439b7f54cc14f2df07ac</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/297172/arch/CYGWIN/installer/curl-7.38.0.297172-windows-297172.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/curl_3p-update-curl/rev/301717/arch/CYGWIN/installer/curl-7.42.1.301717-windows-301717.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
           </map>
         </map>
         <key>version</key>
-        <string>7.38.0.297172</string>
+        <string>7.42.1.301717</string>
       </map>
       <key>db</key>
       <map>
@@ -696,9 +642,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>f577144536fd7c9d26d9f989acf17857</string>
+              <string>44c596c659d32a86972ac9c6f206cb68</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glh-linear_3p-update-glh-linear/rev/297692/arch/Linux/installer/glh_linear-0.0.0-common-297692.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glh-linear_3p-glh-linear/rev/303446/arch/Linux/installer/glh_linear-0.0.0-common-303446.tar.bz2</string>
             </map>
             <key>name</key>
             <string>common</string>
@@ -1506,9 +1452,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ce1261a54d877ab5530ae6a9134a77a3</string>
+              <string>faa1e5b7cf70c143caabe190fa5588ce</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/294906/arch/Linux/installer/llappearance_utility-0.0.1-linux-294906.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
diff --git a/indra/cmake/00-COMPILE-LINK-RUN.txt b/indra/cmake/00-COMPILE-LINK-RUN.txt
index 49b899c50dd1dac56328556ca1c4a0ffdb6be83d..162b22865ca4b9723ded9fc868601a3f8be2be24 100644
--- a/indra/cmake/00-COMPILE-LINK-RUN.txt
+++ b/indra/cmake/00-COMPILE-LINK-RUN.txt
@@ -51,7 +51,6 @@ Compilation
                    WINVER=0x0501                 "                   "
                    _WIN32_WINNT=0x0501           "                   "
                    LL_OS_DRAGDROP_ENABLED=1      "                   "
-                   CARES_STATICLIB               "                   "
                    LIB_NDOF=1                    "                   "
 
     ----------------------------------------------------------------------------
@@ -109,7 +108,6 @@ Compilation
                                          DEBUG_INFO=1
                    LL_DARWIN=1                   "                   "
                    LL_OS_DRAGDROP_ENABLED=1      "                   "
-                   CARES_STATICLIB               "                   "
                    LIB_NDOF=1                    "                   "
 
     ----------------------------------------------------------------------------
diff --git a/indra/cmake/CARes.cmake b/indra/cmake/CARes.cmake
deleted file mode 100755
index baa55aa49dca5120c7a1e8c59454630cc42a4683..0000000000000000000000000000000000000000
--- a/indra/cmake/CARes.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- cmake -*-
-include(Linking)
-include(Prebuilt)
-
-set(CARES_FIND_QUIETLY ON)
-set(CARES_FIND_REQUIRED ON)
-
-if (USESYSTEMLIBS)
-  include(FindCARes)
-else (USESYSTEMLIBS)
-    use_prebuilt_binary(ares)
-    add_definitions("-DCARES_STATICLIB")
-    if (WINDOWS)
-        set(CARES_LIBRARIES areslib)
-    elseif (DARWIN)
-       set(CARES_LIBRARIES cares)
-    else (WINDOWS)
-        set(CARES_LIBRARIES cares)
-    endif (WINDOWS)
-    set(CARES_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/ares)
-endif (USESYSTEMLIBS)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index cd7da5d6c1913e82ba6f982101067adb7789c268..d700c7fd99ff5bd4ee48dc6295b0af1cb7d9599a 100755
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -13,7 +13,6 @@ set(cmake_SOURCE_FILES
     BerkeleyDB.cmake
     Boost.cmake
     BuildVersion.cmake
-    CARes.cmake
     CMakeCopyIfDifferent.cmake
     ConfigurePkgConfig.cmake
     CURL.cmake
@@ -27,7 +26,6 @@ set(cmake_SOURCE_FILES
     FindAPR.cmake
     FindAutobuild.cmake
     FindBerkeleyDB.cmake
-    FindCARes.cmake
     FindFMODEX.cmake
     FindGLH.cmake
     FindGoogleBreakpad.cmake
@@ -58,7 +56,6 @@ set(cmake_SOURCE_FILES
     JsonCpp.cmake
     LLAddBuildTest.cmake
     LLAppearance.cmake
-    LLAppearanceUtility.cmake
     LLAudio.cmake
     LLCharacter.cmake
     LLCommon.cmake
diff --git a/indra/cmake/FindCARes.cmake b/indra/cmake/FindCARes.cmake
deleted file mode 100755
index 1ed5b32913587a5c930586d0788a16b8a7a2554f..0000000000000000000000000000000000000000
--- a/indra/cmake/FindCARes.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- cmake -*-
-
-# - Find c-ares
-# Find the c-ares includes and library
-# This module defines
-#  CARES_INCLUDE_DIR, where to find ares.h, etc.
-#  CARES_LIBRARIES, the libraries needed to use c-ares.
-#  CARES_FOUND, If false, do not try to use c-ares.
-# also defined, but not for general use are
-#  CARES_LIBRARY, where to find the c-ares library.
-
-FIND_PATH(CARES_INCLUDE_DIR ares.h
-/usr/local/include
-/usr/include
-)
-
-SET(CARES_NAMES ${CARES_NAMES} cares)
-FIND_LIBRARY(CARES_LIBRARY
-  NAMES ${CARES_NAMES}
-  PATHS /usr/lib /usr/local/lib
-  )
-
-IF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
-    SET(CARES_LIBRARIES ${CARES_LIBRARY})
-    SET(CARES_FOUND "YES")
-ELSE (CARES_LIBRARY AND CARES_INCLUDE_DIR)
-  SET(CARES_FOUND "NO")
-ENDIF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
-
-
-IF (CARES_FOUND)
-   IF (NOT CARES_FIND_QUIETLY)
-      MESSAGE(STATUS "Found c-ares: ${CARES_LIBRARIES}")
-   ENDIF (NOT CARES_FIND_QUIETLY)
-ELSE (CARES_FOUND)
-   IF (CARES_FIND_REQUIRED)
-      MESSAGE(FATAL_ERROR "Could not find c-ares library")
-   ENDIF (CARES_FIND_REQUIRED)
-ENDIF (CARES_FOUND)
-
-# Deprecated declarations.
-SET (NATIVE_CARES_INCLUDE_PATH ${CARES_INCLUDE_DIR} )
-GET_FILENAME_COMPONENT (NATIVE_CARES_LIB_PATH ${CARES_LIBRARY} PATH)
-
-MARK_AS_ADVANCED(
-  CARES_LIBRARY
-  CARES_INCLUDE_DIR
-  )
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index ac5c5c6a2a67b48c1f26b8c3c815518770eda527..db8b95dbe2e80690dafed9a306206d240bc23f1c 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -35,6 +35,7 @@ INCLUDE(GoogleMock)
     ${APRUTIL_LIBRARIES}
     ${APR_LIBRARIES}
     llcommon
+    llcorehttp
     )
   IF(NOT "${project}" STREQUAL "llmath")
     # add llmath as a dep unless the tested module *is* llmath!
@@ -49,6 +50,9 @@ INCLUDE(GoogleMock)
     ${GOOGLEMOCK_INCLUDE_DIRS}
     )
   SET(alltest_LIBRARIES
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
     ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
@@ -191,6 +195,9 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
 
   SET(libraries
     ${library_dependencies}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
     ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     )
diff --git a/indra/cmake/LLAppearance.cmake b/indra/cmake/LLAppearance.cmake
index bd3795a5262b0dcbca26779ba7353e382ad38c77..ae265d07e395c3480ff62fac6ba615fee4dd44ba 100644
--- a/indra/cmake/LLAppearance.cmake
+++ b/indra/cmake/LLAppearance.cmake
@@ -1,6 +1,9 @@
 # -*- cmake -*-
 
 include(Variables)
+include(Boost)
+include(LLMessage)
+include(LLCoreHttp)
 
 set(LLAPPEARANCE_INCLUDE_DIRS
     ${LIBS_OPEN_DIR}/llappearance
@@ -12,6 +15,13 @@ if (BUILD_HEADLESS)
     )
 endif (BUILD_HEADLESS)
 
-set(LLAPPEARANCE_LIBRARIES llappearance)
+set(LLAPPEARANCE_LIBRARIES llappearance
+    llmessage
+    llcorehttp
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
+    )
+
 
 
diff --git a/indra/cmake/LLAppearanceUtility.cmake b/indra/cmake/LLAppearanceUtility.cmake
index 709b91c134f21c663b680c932bbdd4b8e3c216e6..28b49bf75f73c8f532b9bc4726edff3f4b31915e 100644
--- a/indra/cmake/LLAppearanceUtility.cmake
+++ b/indra/cmake/LLAppearanceUtility.cmake
@@ -1,5 +1,6 @@
 # -*- cmake -*-
 include(Prebuilt)
+include(Boost)
 
 # Linux proprietary build only
 if (INSTALL_PROPRIETARY)
@@ -10,3 +11,4 @@ if (INSTALL_PROPRIETARY)
     endif (LINUX)
 endif (INSTALL_PROPRIETARY)
 
+
diff --git a/indra/cmake/LLCoreHttp.cmake b/indra/cmake/LLCoreHttp.cmake
index 61e4b23d986de222dec352c135443a545dfdc873..379ae207ded3da735c9de36bc7d7bf8a0983bfcf 100755
--- a/indra/cmake/LLCoreHttp.cmake
+++ b/indra/cmake/LLCoreHttp.cmake
@@ -1,16 +1,17 @@
 # -*- cmake -*-
 
-include(CARes)
 include(CURL)
 include(OpenSSL)
 include(Boost)
 
 set(LLCOREHTTP_INCLUDE_DIRS
     ${LIBS_OPEN_DIR}/llcorehttp
-    ${CARES_INCLUDE_DIRS}
     ${CURL_INCLUDE_DIRS}
     ${OPENSSL_INCLUDE_DIRS}
     ${BOOST_INCLUDE_DIRS}
     )
 
-set(LLCOREHTTP_LIBRARIES llcorehttp)
+set(LLCOREHTTP_LIBRARIES llcorehttp
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY})
diff --git a/indra/cmake/LLMessage.cmake b/indra/cmake/LLMessage.cmake
index 0143d04fd76f55cf5df0a17c0afe9d7fa1dea8db..7be53ec0ec3441a7534b27f70af158f88c69757d 100755
--- a/indra/cmake/LLMessage.cmake
+++ b/indra/cmake/LLMessage.cmake
@@ -1,13 +1,11 @@
 # -*- cmake -*-
 
-include(CARes)
 include(CURL)
 include(OpenSSL)
 include(XmlRpcEpi)
 
 set(LLMESSAGE_INCLUDE_DIRS
     ${LIBS_OPEN_DIR}/llmessage
-    ${CARES_INCLUDE_DIRS}
     ${CURL_INCLUDE_DIRS}
     ${OPENSSL_INCLUDE_DIRS}
     )
diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt
index c0fc1b2be0ecce2bceb1b2263c6e29a77c3ca09f..029096df3732fc9ab65cecc9ec3bfaa7e98ce573 100755
--- a/indra/linux_crash_logger/CMakeLists.txt
+++ b/indra/linux_crash_logger/CMakeLists.txt
@@ -4,6 +4,7 @@ project(linux_crash_logger)
 
 include(00-Common)
 include(GLH)
+include(LLCoreHttp)
 include(LLCommon)
 include(LLCrashLogger)
 include(LLMath)
@@ -13,8 +14,10 @@ include(LLXML)
 include(Linking)
 include(UI)
 include(FreeType)
+include(Boost)
 
 include_directories(
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLCRASHLOGGER_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
@@ -53,6 +56,10 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
 
 add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})
 
+# llcommon uses `clock_gettime' which is provided by librt on linux.
+set(LIBRT_LIBRARY rt)
+
+
 target_link_libraries(linux-crash-logger
     ${LLCRASHLOGGER_LIBRARIES}
     ${LLVFS_LIBRARIES}
@@ -60,10 +67,14 @@ target_link_libraries(linux-crash-logger
     ${LLMESSAGE_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
     ${UI_LIBRARIES}
     ${DB_LIBRARIES}
     ${FREETYPE_LIBRARIES}
+    ${LIBRT_LIBRARY}
     )
 
 add_custom_target(linux-crash-logger-target ALL
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index 0dbd58b7cd7e6a22aa6a7e630923e9636ac9b764..20eb4678dd223b987fc535d89ef06ba43421b1ee 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -9,6 +9,7 @@ include(LLImage)
 include(LLInventory)
 include(LLMath)
 include(LLMessage)
+include(LLCoreHttp)
 include(LLRender)
 include(LLVFS)
 include(LLWindow)
@@ -86,6 +87,8 @@ target_link_libraries(llappearance
     ${LLMATH_LIBRARIES}
     ${LLXML_LIBRARIES}
     ${LLMATH_LIBRARIES}
+    ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
     )
 
@@ -101,6 +104,8 @@ if (BUILD_HEADLESS)
       ${LLMATH_LIBRARIES}
       ${LLXML_LIBRARIES}
       ${LLMATH_LIBRARIES}
+      ${LLMESSAGE_LIBRARIES}
+      ${LLCOREHTTP_LIBRARIES}
       ${LLCOMMON_LIBRARIES}
       )
 endif (BUILD_HEADLESS)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 1459b9ada2785be76b7a8183123832be4895a2b1..8ae487354abf3fd333222cd97f3e612ab2660fa9 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -8,6 +8,7 @@ include(LLCommon)
 include(Linking)
 include(Boost)
 include(LLSharedLibs)
+include(JsonCpp)
 include(GoogleBreakpad)
 include(GooglePerfTools)
 include(Copy3rdPartyLibs)
@@ -17,6 +18,7 @@ include(URIPARSER)
 include_directories(
     ${EXPAT_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
+    ${JSONCPP_INCLUDE_DIR}
     ${ZLIB_INCLUDE_DIRS}
     ${BREAKPAD_INCLUDE_DIRECTORIES}
     ${URIPARSER_INCLUDE_DIRS}
@@ -37,6 +39,7 @@ set(llcommon_SOURCE_FILES
     llbase32.cpp
     llbase64.cpp
     llbitpack.cpp
+    llcallbacklist.cpp
     llcommon.cpp
     llcommonutils.cpp
     llcoros.cpp
@@ -85,6 +88,7 @@ set(llcommon_SOURCE_FILES
     llrefcount.cpp
     llrun.cpp
     llsd.cpp
+    llsdjson.cpp
     llsdparam.cpp
     llsdserialize.cpp
     llsdserialize_xml.cpp
@@ -129,6 +133,7 @@ set(llcommon_HEADER_FILES
     llbase64.h
     llbitpack.h
     llboost.h
+    llcallbacklist.h
     llcommon.h
     llcommonutils.h
     llcoros.h
@@ -193,6 +198,7 @@ set(llcommon_HEADER_FILES
     llrefcount.h
     llsafehandle.h
     llsd.h
+    llsdjson.h
     llsdparam.h
     llsdserialize.h
     llsdserialize_xml.h
@@ -260,10 +266,14 @@ target_link_libraries(
     ${APRUTIL_LIBRARIES}
     ${APR_LIBRARIES}
     ${EXPAT_LIBRARIES}
+    ${JSONCPP_LIBRARIES}
     ${ZLIB_LIBRARIES}
     ${WINDOWS_LIBRARIES}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
     ${BOOST_REGEX_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
     ${GOOGLE_PERFTOOLS_LIBRARIES}
     ${URIPARSER_LIBRARIES}
     )
@@ -306,7 +316,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY};${BOOST_THREAD_LIBRARY};${BOOST_COROUTINE_LIBRARY};${BOOST_SYSTEM_LIBRARY}")
+  LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_COROUTINE_LIBRARY};${BOOST_CONTEXT_LIBRARY};${BOOST_THREAD_LIBRARY};${BOOST_SYSTEM_LIBRARY}")
   LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
diff --git a/indra/llcommon/fix_macros.h b/indra/llcommon/fix_macros.h
index ef959decffeb755146927b15a4b4c93c13599faa..43c09c54bc364f471a01e9433c0196c659ea24c5 100755
--- a/indra/llcommon/fix_macros.h
+++ b/indra/llcommon/fix_macros.h
@@ -16,10 +16,6 @@
 // these macros all over again.
 
 // who injects MACROS with such generic names?! Grr.
-#ifdef equivalent
-#undef equivalent
-#endif 
-
 #ifdef check
 #undef check
 #endif
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index 5cfcdab41cd331c43df806e628e0ace851492b89..e5a913a6a99c56214fc7365b2c13957aae0a810b 100755
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -51,6 +51,7 @@
 #include <cstdlib>
 #include <ctime>
 #include <iosfwd>
+#include <memory>
 
 // Linden only libs in alpha-order other than stdtypes.h
 // *NOTE: Please keep includes here to a minimum, see above.
diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..541ff75ee4d834382d61dba0a7f2522084921708
--- /dev/null
+++ b/indra/llcommon/llcallbacklist.cpp
@@ -0,0 +1,230 @@
+/** 
+ * @file llcallbacklist.cpp
+ * @brief A simple list of callback functions to call.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llcallbacklist.h"
+#include "lleventtimer.h"
+#include "llerrorlegacy.h"
+
+// Globals
+//
+LLCallbackList gIdleCallbacks;
+
+//
+// Member functions
+//
+
+LLCallbackList::LLCallbackList()
+{
+	// nothing
+}
+
+LLCallbackList::~LLCallbackList()
+{
+}
+
+
+void LLCallbackList::addFunction( callback_t func, void *data)
+{
+	if (!func)
+	{
+		return;
+	}
+
+	// only add one callback per func/data pair
+	//
+	if (containsFunction(func))
+	{
+		return;
+	}
+	
+	callback_pair_t t(func, data);
+	mCallbackList.push_back(t);
+}
+
+bool LLCallbackList::containsFunction( callback_t func, void *data)
+{
+	callback_pair_t t(func, data);
+	callback_list_t::iterator iter = find(func,data);
+	if (iter != mCallbackList.end())
+	{
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
+
+bool LLCallbackList::deleteFunction( callback_t func, void *data)
+{
+	callback_list_t::iterator iter = find(func,data);
+	if (iter != mCallbackList.end())
+	{
+		mCallbackList.erase(iter);
+		return TRUE;
+	}
+	else
+	{
+		return FALSE;
+	}
+}
+
+inline 
+LLCallbackList::callback_list_t::iterator
+LLCallbackList::find(callback_t func, void *data)
+{
+	callback_pair_t t(func, data);
+	return std::find(mCallbackList.begin(), mCallbackList.end(), t);
+}
+
+void LLCallbackList::deleteAllFunctions()
+{
+	mCallbackList.clear();
+}
+
+
+void LLCallbackList::callFunctions()
+{
+	for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end();  )
+	{
+		callback_list_t::iterator curiter = iter++;
+		curiter->first(curiter->second);
+	}
+}
+
+// Shim class to allow arbitrary boost::bind
+// expressions to be run as one-time idle callbacks.
+class OnIdleCallbackOneTime
+{
+public:
+	OnIdleCallbackOneTime(nullary_func_t callable):
+		mCallable(callable)
+	{
+	}
+	static void onIdle(void *data)
+	{
+		gIdleCallbacks.deleteFunction(onIdle, data);
+		OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
+		self->call();
+		delete self;
+	}
+	void call()
+	{
+		mCallable();
+	}
+private:
+	nullary_func_t mCallable;
+};
+
+void doOnIdleOneTime(nullary_func_t callable)
+{
+	OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
+	gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
+}
+
+// Shim class to allow generic boost functions to be run as
+// recurring idle callbacks.  Callable should return true when done,
+// false to continue getting called.
+class OnIdleCallbackRepeating
+{
+public:
+	OnIdleCallbackRepeating(bool_func_t callable):
+		mCallable(callable)
+	{
+	}
+	// Will keep getting called until the callable returns true.
+	static void onIdle(void *data)
+	{
+		OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
+		bool done = self->call();
+		if (done)
+		{
+			gIdleCallbacks.deleteFunction(onIdle, data);
+			delete self;
+		}
+	}
+	bool call()
+	{
+		return mCallable();
+	}
+private:
+	bool_func_t mCallable;
+};
+
+void doOnIdleRepeating(bool_func_t callable)
+{
+	OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
+	gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
+}
+
+class NullaryFuncEventTimer: public LLEventTimer
+{
+public:
+	NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
+		LLEventTimer(seconds),
+		mCallable(callable)
+	{
+	}
+
+private:
+	BOOL tick()
+	{
+		mCallable();
+		return TRUE;
+	}
+
+	nullary_func_t mCallable;
+};
+
+// Call a given callable once after specified interval.
+void doAfterInterval(nullary_func_t callable, F32 seconds)
+{
+	new NullaryFuncEventTimer(callable, seconds);
+}
+
+class BoolFuncEventTimer: public LLEventTimer
+{
+public:
+	BoolFuncEventTimer(bool_func_t callable, F32 seconds):
+		LLEventTimer(seconds),
+		mCallable(callable)
+	{
+	}
+private:
+	BOOL tick()
+	{
+		return mCallable();
+	}
+
+	bool_func_t mCallable;
+};
+
+// Call a given callable every specified number of seconds, until it returns true.
+void doPeriodically(bool_func_t callable, F32 seconds)
+{
+	new BoolFuncEventTimer(callable, seconds);
+}
diff --git a/indra/newview/llcallbacklist.h b/indra/llcommon/llcallbacklist.h
old mode 100755
new mode 100644
similarity index 76%
rename from indra/newview/llcallbacklist.h
rename to indra/llcommon/llcallbacklist.h
index 0516c9cdb44e663d47d123b555a7550ce0c774c3..89716cd74ca985696fbc785d5b99b22a704ae91d
--- a/indra/newview/llcallbacklist.h
+++ b/indra/llcommon/llcallbacklist.h
@@ -28,27 +28,34 @@
 #define LL_LLCALLBACKLIST_H
 
 #include "llstl.h"
+#include <boost/function.hpp>
+#include <list>
 
 class LLCallbackList
 {
 public:
 	typedef void (*callback_t)(void*);
+
+	typedef std::pair< callback_t,void* >	callback_pair_t;
+	// NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
+	//
+	typedef std::list< callback_pair_t >	callback_list_t; 
 	
 	LLCallbackList();
 	~LLCallbackList();
 
-	void addFunction( callback_t func, void *data = NULL );		// register a callback, which will be called as func(data)
-	BOOL containsFunction( callback_t func, void *data = NULL );	// true if list already contains the function/data pair
-	BOOL deleteFunction( callback_t func, void *data = NULL );		// removes the first instance of this function/data pair from the list, false if not found
-	void callFunctions();												// calls all functions
+	void addFunction( callback_t func, void *data = NULL );			// register a callback, which will be called as func(data)
+	bool containsFunction( callback_t func, void *data = NULL );	// true if list already contains the function/data pair
+	bool deleteFunction( callback_t func, void *data = NULL );		// removes the first instance of this function/data pair from the list, false if not found
+	void callFunctions();														// calls all functions
 	void deleteAllFunctions();
 
 	static void test();
 
 protected:
-	// Use a list so that the callbacks are ordered in case that matters
-	typedef std::pair<callback_t,void*> callback_pair_t;
-	typedef std::list<callback_pair_t > callback_list_t;
+
+	inline callback_list_t::iterator find(callback_t func, void *data);
+
 	callback_list_t	mCallbackList;
 };
 
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index baaddcaed1ea64d1cbc425336b84000b55227cd6..d76401d01b394998f8e77eee0b947b16d6fadaea 100755
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -39,6 +39,44 @@
 #include "llerror.h"
 #include "stringize.h"
 
+// do nothing, when we need nothing done
+void LLCoros::no_cleanup(CoroData*) {}
+
+// CoroData for the currently-running coroutine. Use a thread_specific_ptr
+// because each thread potentially has its own distinct pool of coroutines.
+// This thread_specific_ptr does NOT own the CoroData object! That's owned by
+// LLCoros::mCoros. It merely identifies it. For this reason we instantiate
+// it with a no-op cleanup function.
+boost::thread_specific_ptr<LLCoros::CoroData>
+LLCoros::sCurrentCoro(LLCoros::no_cleanup);
+
+//static
+LLCoros::coro::self& LLCoros::get_self()
+{
+    CoroData* current = sCurrentCoro.get();
+    if (! current)
+    {
+        LL_ERRS("LLCoros") << "Calling get_self() from non-coroutine context!" << LL_ENDL;
+    }
+    return *current->mSelf;
+}
+
+llcoro::Suspending::Suspending():
+    mSuspended(LLCoros::sCurrentCoro.get())
+{
+    // Revert mCurrentCoro to the value it had at the moment we last switched
+    // into this coroutine.
+    LLCoros::sCurrentCoro.reset(mSuspended->mPrev);
+}
+
+llcoro::Suspending::~Suspending()
+{
+    // Okay, we're back, update our mPrev
+    mSuspended->mPrev = LLCoros::sCurrentCoro.get();
+    // and reinstate our sCurrentCoro.
+    LLCoros::sCurrentCoro.reset(mSuspended);
+}
+
 LLCoros::LLCoros():
     // MAINT-2724: default coroutine stack size too small on Windows.
     // Previously we used
@@ -58,9 +96,9 @@ bool LLCoros::cleanup(const LLSD&)
     {
         // Has this coroutine exited (normal return, exception, exit() call)
         // since last tick?
-        if (mi->second->exited())
+        if (mi->second->mCoro.exited())
         {
-			   LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
+            LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
             // The erase() call will invalidate its passed iterator value --
             // so increment mi FIRST -- but pass its original value to
             // erase(). This is what postincrement is all about.
@@ -94,7 +132,7 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
     {
         if (mCoros.find(name) == mCoros.end())
         {
-			   LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
+            LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
             return name;
         }
     }
@@ -114,20 +152,15 @@ bool LLCoros::kill(const std::string& name)
     return true;
 }
 
-std::string LLCoros::getNameByID(const void* self_id) const
+std::string LLCoros::getName() const
 {
-    // Walk the existing coroutines, looking for one from which the 'self_id'
-    // passed to us comes.
-    for (CoroMap::const_iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; ++mi)
+    CoroData* current = sCurrentCoro.get();
+    if (! current)
     {
-        namespace coro_private = boost::dcoroutines::detail;
-        if (static_cast<void*>(coro_private::coroutine_accessor::get_impl(const_cast<coro&>(*mi->second)).get())
-            == self_id)
-        {
-            return mi->first;
-        }
+        // not in a coroutine
+        return "";
     }
-    return "";
+    return current->mName;
 }
 
 void LLCoros::setStackSize(S32 stacksize)
@@ -136,10 +169,24 @@ void LLCoros::setStackSize(S32 stacksize)
     mStackSize = stacksize;
 }
 
+// Top-level wrapper around caller's coroutine callable. This function accepts
+// the coroutine library's implicit coro::self& parameter and sets sCurrentSelf
+// but does not pass it down to the caller's callable.
+void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& callable)
+{
+    // capture the 'self' param in CoroData
+    data->mSelf = &self;
+    // run the code the caller actually wants in the coroutine
+    callable();
+    // This cleanup isn't perfectly symmetrical with the way we initially set
+    // data->mPrev, but this is our last chance to reset mCurrentCoro.
+    sCurrentCoro.reset(data->mPrev);
+}
+
 /*****************************************************************************
 *   MUST BE LAST
 *****************************************************************************/
-// Turn off MSVC optimizations for just LLCoros::launchImpl() -- see
+// Turn off MSVC optimizations for just LLCoros::launch() -- see
 // DEV-32777. But MSVC doesn't support push/pop for optimization flags as it
 // does for warning suppression, and we really don't want to force
 // optimization ON for other code even in Debug or RelWithDebInfo builds.
@@ -147,15 +194,33 @@ void LLCoros::setStackSize(S32 stacksize)
 #if LL_MSVC
 // work around broken optimizations
 #pragma warning(disable: 4748)
+#pragma warning(disable: 4355) // 'this' used in initializer list: yes, intentionally
 #pragma optimize("", off)
 #endif // LL_MSVC
 
-std::string LLCoros::launchImpl(const std::string& prefix, coro* newCoro)
+LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name,
+                            const callable_t& callable, S32 stacksize):
+    mPrev(prev),
+    mName(name),
+    // Wrap the caller's callable in our toplevel() function so we can manage
+    // sCurrentCoro appropriately at startup and shutdown of each coroutine.
+    mCoro(boost::bind(toplevel, _1, this, callable), stacksize),
+    mSelf(0)
+{
+}
+
+std::string LLCoros::launch(const std::string& prefix, const callable_t& callable)
 {
     std::string name(generateDistinctName(prefix));
+    // pass the current value of sCurrentCoro as previous context
+    CoroData* newCoro = new CoroData(sCurrentCoro.get(), name,
+                                     callable, mStackSize);
+    // Store it in our pointer map
     mCoros.insert(name, newCoro);
+    // also set it as current
+    sCurrentCoro.reset(newCoro);
     /* Run the coroutine until its first wait, then return here */
-    (*newCoro)(std::nothrow);
+    (newCoro->mCoro)(std::nothrow);
     return name;
 }
 
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 01ee11da1ac180419c87b7b6d26d9e0667e0399c..56eed8cafed0a3717c7e16735cf1388f81349833 100755
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -32,12 +32,17 @@
 #include <boost/dcoroutine/coroutine.hpp>
 #include "llsingleton.h"
 #include <boost/ptr_container/ptr_map.hpp>
+#include <boost/function.hpp>
+#include <boost/thread/tss.hpp>
 #include <string>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/repetition/enum_binary_params.hpp>
-#include <boost/preprocessor/iteration/local.hpp>
 #include <stdexcept>
 
+// forward-declare helper class
+namespace llcoro
+{
+class Suspending;
+}
+
 /**
  * Registry of named Boost.Coroutine instances
  *
@@ -80,8 +85,8 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
 public:
     /// Canonical boost::dcoroutines::coroutine signature we use
     typedef boost::dcoroutines::coroutine<void()> coro;
-    /// Canonical 'self' type
-    typedef coro::self self;
+    /// Canonical callable type
+    typedef boost::function<void()> callable_t;
 
     /**
      * Create and start running a new coroutine with specified name. The name
@@ -94,39 +99,33 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
      * {
      * public:
      *     ...
-     *     // Do NOT NOT NOT accept reference params other than 'self'!
+     *     // Do NOT NOT NOT accept reference params!
      *     // Pass by value only!
-     *     void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
+     *     void myCoroutineMethod(std::string, LLSD);
      *     ...
      * };
      * ...
      * std::string name = LLCoros::instance().launch(
-     *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
+     *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this,
      *                          "somestring", LLSD(17));
      * @endcode
      *
-     * Your function/method must accept LLCoros::self& as its first parameter.
-     * It can accept any other parameters you want -- but ONLY BY VALUE!
-     * Other reference parameters are a BAD IDEA! You Have Been Warned. See
+     * Your function/method can accept any parameters you want -- but ONLY BY
+     * VALUE! Reference parameters are a BAD IDEA! You Have Been Warned. See
      * DEV-32777 comments for an explanation.
      *
-     * Pass a callable that accepts the single LLCoros::self& parameter. It
-     * may work to pass a free function whose only parameter is 'self'; for
-     * all other cases use boost::bind(). Of course, for a non-static class
-     * method, the first parameter must be the class instance. Use the
-     * placeholder _1 for the 'self' parameter. Any other parameters should be
-     * passed via the bind() expression.
+     * Pass a nullary callable. It works to directly pass a nullary free
+     * function (or static method); for all other cases use boost::bind(). Of
+     * course, for a non-static class method, the first parameter must be the
+     * class instance. Any other parameters should be passed via the bind()
+     * expression.
      *
      * launch() tweaks the suggested name so it won't collide with any
      * existing coroutine instance, creates the coroutine instance, registers
      * it with the tweaked name and runs it until its first wait. At that
      * point it returns the tweaked name.
      */
-    template <typename CALLABLE>
-    std::string launch(const std::string& prefix, const CALLABLE& callable)
-    {
-        return launchImpl(prefix, new coro(callable, mStackSize));
-    }
+    std::string launch(const std::string& prefix, const callable_t& callable);
 
     /**
      * Abort a running coroutine by name. Normally, when a coroutine either
@@ -138,33 +137,85 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
     bool kill(const std::string& name);
 
     /**
-     * From within a coroutine, pass its @c self object to look up the
-     * (tweaked) name string by which this coroutine is registered. Returns
-     * the empty string if not found (e.g. if the coroutine was launched by
-     * hand rather than using LLCoros::launch()).
+     * From within a coroutine, look up the (tweaked) name string by which
+     * this coroutine is registered. Returns the empty string if not found
+     * (e.g. if the coroutine was launched by hand rather than using
+     * LLCoros::launch()).
      */
-    template <typename COROUTINE_SELF>
-    std::string getName(const COROUTINE_SELF& self) const
-    {
-        return getNameByID(self.get_id());
-    }
-
-    /// getName() by self.get_id()
-    std::string getNameByID(const void* self_id) const;
+    std::string getName() const;
 
     /// for delayed initialization
     void setStackSize(S32 stacksize);
 
+    /// get the current coro::self& for those who really really care
+    static coro::self& get_self();
+
 private:
-    friend class LLSingleton<LLCoros>;
     LLCoros();
-    std::string launchImpl(const std::string& prefix, coro* newCoro);
+    friend class LLSingleton<LLCoros>;
+    friend class llcoro::Suspending;
     std::string generateDistinctName(const std::string& prefix) const;
     bool cleanup(const LLSD&);
+    struct CoroData;
+    static void no_cleanup(CoroData*);
+    static void toplevel(coro::self& self, CoroData* data, const callable_t& callable);
 
     S32 mStackSize;
-    typedef boost::ptr_map<std::string, coro> CoroMap;
+
+    // coroutine-local storage, as it were: one per coro we track
+    struct CoroData
+    {
+        CoroData(CoroData* prev, const std::string& name,
+                 const callable_t& callable, S32 stacksize);
+
+        // The boost::dcoroutines library supports asymmetric coroutines. Every
+        // time we context switch out of a coroutine, we pass control to the
+        // previously-active one (or to the non-coroutine stack owned by the
+        // thread). So our management of the "current" coroutine must be able to
+        // restore the previous value when we're about to switch away.
+        CoroData* mPrev;
+        // tweaked name of the current coroutine
+        const std::string mName;
+        // the actual coroutine instance
+        LLCoros::coro mCoro;
+        // When the dcoroutine library calls a top-level callable, it implicitly
+        // passes coro::self& as the first parameter. All our consumer code used
+        // to explicitly pass coro::self& down through all levels of call stack,
+        // because at the leaf level we need it for context-switching. But since
+        // coroutines are based on cooperative switching, we can cause the
+        // top-level entry point to stash a pointer to the currently-running
+        // coroutine, and manage it appropriately as we switch out and back in.
+        // That eliminates the need to pass it as an explicit parameter down
+        // through every level, which is unfortunately viral in nature. Finding it
+        // implicitly rather than explicitly allows minor maintenance in which a
+        // leaf-level function adds a new async I/O call that suspends the calling
+        // coroutine, WITHOUT having to propagate coro::self& through every
+        // function signature down to that point -- and of course through every
+        // other caller of every such function.
+        LLCoros::coro::self* mSelf;
+    };
+    typedef boost::ptr_map<std::string, CoroData> CoroMap;
     CoroMap mCoros;
+
+    // identify the current coroutine's CoroData
+    static boost::thread_specific_ptr<LLCoros::CoroData> sCurrentCoro;
+};
+
+namespace llcoro
+{
+
+/// Instantiate one of these in a block surrounding any leaf point when
+/// control literally switches away from this coroutine.
+class Suspending
+{
+public:
+    Suspending();
+    ~Suspending();
+
+private:
+    LLCoros::CoroData* mSuspended;
 };
 
+} // namespace llcoro
+
 #endif /* ! defined(LL_LLCOROS_H) */
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 63040e1772a15b4a9239127df183e1b15a3a0df8..b1b5e9be7d7a913be6160cfa49a8cebb701becc7 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -354,6 +354,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
 #define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
 // alternative to llassert_always that prints explanatory message
+#define LL_WARNS_IF(exp, ...)	if (exp) LL_WARNS(##__VA_ARGS__) << "(" #exp ")"
 #define LL_ERRS_IF(exp, ...)	if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"
 
 // Only print the log message once (good for warnings or infos that would otherwise
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 81cc33fbbaca018c6f26100e230075579f037e9e..c9bfcacedca02fc4006f8630b0ad81f3122537a6 100755
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -34,38 +34,63 @@
 #include <map>
 // std headers
 // external library headers
+#include <boost/dcoroutine/coroutine.hpp>
+#include <boost/dcoroutine/future.hpp>
 // other Linden headers
 #include "llsdserialize.h"
 #include "llerror.h"
 #include "llcoros.h"
 
-std::string LLEventDetail::listenerNameForCoroImpl(const void* self_id)
+namespace
 {
-    // First, if this coroutine was launched by LLCoros::launch(), find that name.
-    std::string name(LLCoros::instance().getNameByID(self_id));
+
+/**
+ * suspendUntilEventOn() permits a coroutine to temporarily listen on an
+ * LLEventPump any number of times. We don't really want to have to ask
+ * the caller to label each such call with a distinct string; the whole
+ * point of suspendUntilEventOn() is to present a nice sequential interface to
+ * the underlying LLEventPump-with-named-listeners machinery. So we'll use
+ * LLEventPump::inventName() to generate a distinct name for each
+ * temporary listener. On the other hand, because a given coroutine might
+ * call suspendUntilEventOn() any number of times, we don't really want to
+ * consume an arbitrary number of generated inventName()s: that namespace,
+ * though large, is nonetheless finite. So we memoize an invented name for
+ * each distinct coroutine instance.
+ */
+std::string listenerNameForCoro()
+{
+    // If this coroutine was launched by LLCoros::launch(), find that name.
+    std::string name(LLCoros::instance().getName());
     if (! name.empty())
     {
         return name;
     }
-    // Apparently this coroutine wasn't launched by LLCoros::launch(). Check
-    // whether we have a memo for this self_id.
-    typedef std::map<const void*, std::string> MapType;
-    static MapType memo;
-    MapType::const_iterator found = memo.find(self_id);
-    if (found != memo.end())
-    {
-        // this coroutine instance has called us before, reuse same name
-        return found->second;
-    }
     // this is the first time we've been called for this coroutine instance
     name = LLEventPump::inventName("coro");
-    memo[self_id] = name;
-    LL_INFOS("LLEventCoro") << "listenerNameForCoroImpl(" << self_id << "): inventing coro name '"
+    LL_INFOS("LLEventCoro") << "listenerNameForCoro(): inventing coro name '"
                             << name << "'" << LL_ENDL;
     return name;
 }
 
-void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value)
+/**
+ * Implement behavior described for postAndSuspend()'s @a replyPumpNamePath
+ * parameter:
+ *
+ * * If <tt>path.isUndefined()</tt>, do nothing.
+ * * If <tt>path.isString()</tt>, @a dest is an LLSD map: store @a value
+ *   into <tt>dest[path.asString()]</tt>.
+ * * If <tt>path.isInteger()</tt>, @a dest is an LLSD array: store @a
+ *   value into <tt>dest[path.asInteger()]</tt>.
+ * * If <tt>path.isArray()</tt>, iteratively apply the rules above to step
+ *   down through the structure of @a dest. The last array entry in @a
+ *   path specifies the entry in the lowest-level structure in @a dest
+ *   into which to store @a value.
+ *
+ * @note
+ * In the degenerate case in which @a path is an empty array, @a dest will
+ * @em become @a value rather than @em containing it.
+ */
+void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value)
 {
     if (rawPath.isUndefined())
     {
@@ -118,6 +143,155 @@ void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD&
     *pdest = value;
 }
 
+} // anonymous
+
+void llcoro::suspend()
+{
+    // By viewer convention, we post an event on the "mainloop" LLEventPump
+    // each iteration of the main event-handling loop. So waiting for a single
+    // event on "mainloop" gives us a one-frame suspend.
+    suspendUntilEventOn("mainloop");
+}
+
+LLSD llcoro::postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+                 const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath)
+{
+    // declare the future
+    boost::dcoroutines::future<LLSD> future(LLCoros::get_self());
+    // make a callback that will assign a value to the future, and listen on
+    // the specified LLEventPump with that callback
+    std::string listenerName(listenerNameForCoro());
+    LLTempBoundListener connection(
+        replyPump.getPump().listen(listenerName,
+                                   voidlistener(boost::dcoroutines::make_callback(future))));
+    // skip the "post" part if requestPump is default-constructed
+    if (requestPump)
+    {
+        // If replyPumpNamePath is non-empty, store the replyPump name in the
+        // request event.
+        LLSD modevent(event);
+        storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName());
+        LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
+                                 << " posting to " << requestPump.getPump().getName()
+                                 << LL_ENDL;
+
+        // *NOTE:Mani - Removed because modevent could contain user's hashed passwd.
+        //                         << ": " << modevent << LL_ENDL;
+        requestPump.getPump().post(modevent);
+    }
+    LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
+                             << " about to wait on LLEventPump " << replyPump.getPump().getName()
+                             << LL_ENDL;
+    // trying to dereference ("resolve") the future makes us wait for it
+    LLSD value;
+    {
+        // instantiate Suspending to manage the "current" coroutine
+        llcoro::Suspending suspended;
+        value = *future;
+    } // destroy Suspending as soon as we're back
+    LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
+                             << " resuming with " << value << LL_ENDL;
+    // returning should disconnect the connection
+    return value;
+}
+
+namespace
+{
+
+/**
+ * This helper is specifically for the two-pump version of suspendUntilEventOn().
+ * We use a single future object, but we want to listen on two pumps with it.
+ * Since we must still adapt from (the callable constructed by)
+ * boost::dcoroutines::make_callback() (void return) to provide an event
+ * listener (bool return), we've adapted VoidListener for the purpose. The
+ * basic idea is that we construct a distinct instance of WaitForEventOnHelper
+ * -- binding different instance data -- for each of the pumps. Then, when a
+ * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine
+ * that LLSD with its discriminator to feed the future object.
+ */
+template <typename LISTENER>
+class WaitForEventOnHelper
+{
+public:
+    WaitForEventOnHelper(const LISTENER& listener, int discriminator):
+        mListener(listener),
+        mDiscrim(discriminator)
+    {}
+    // this signature is required for an LLEventPump listener
+    bool operator()(const LLSD& event)
+    {
+        // our future object is defined to accept LLEventWithID
+        mListener(LLEventWithID(event, mDiscrim));
+        // don't swallow the event, let other listeners see it
+        return false;
+    }
+private:
+    LISTENER mListener;
+    const int mDiscrim;
+};
+
+/// WaitForEventOnHelper type-inference helper
+template <typename LISTENER>
+WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator)
+{
+    return WaitForEventOnHelper<LISTENER>(listener, discriminator);
+}
+
+} // anonymous
+
+namespace llcoro
+{
+
+LLEventWithID postAndSuspend2(const LLSD& event,
+                           const LLEventPumpOrPumpName& requestPump,
+                           const LLEventPumpOrPumpName& replyPump0,
+                           const LLEventPumpOrPumpName& replyPump1,
+                           const LLSD& replyPump0NamePath,
+                           const LLSD& replyPump1NamePath)
+{
+    // declare the future
+    boost::dcoroutines::future<LLEventWithID> future(LLCoros::get_self());
+    // either callback will assign a value to this future; listen on
+    // each specified LLEventPump with a callback
+    std::string name(listenerNameForCoro());
+    LLTempBoundListener connection0(
+        replyPump0.getPump().listen(name + "a",
+                                    wfeoh(boost::dcoroutines::make_callback(future), 0)));
+    LLTempBoundListener connection1(
+        replyPump1.getPump().listen(name + "b",
+                                    wfeoh(boost::dcoroutines::make_callback(future), 1)));
+    // skip the "post" part if requestPump is default-constructed
+    if (requestPump)
+    {
+        // If either replyPumpNamePath is non-empty, store the corresponding
+        // replyPump name in the request event.
+        LLSD modevent(event);
+        storeToLLSDPath(modevent, replyPump0NamePath,
+                        replyPump0.getPump().getName());
+        storeToLLSDPath(modevent, replyPump1NamePath,
+                        replyPump1.getPump().getName());
+        LL_DEBUGS("lleventcoro") << "postAndSuspend2(): coroutine " << name
+                                 << " posting to " << requestPump.getPump().getName()
+                                 << ": " << modevent << LL_ENDL;
+        requestPump.getPump().post(modevent);
+    }
+    LL_DEBUGS("lleventcoro") << "postAndSuspend2(): coroutine " << name
+                             << " about to wait on LLEventPumps " << replyPump0.getPump().getName()
+                             << ", " << replyPump1.getPump().getName() << LL_ENDL;
+    // trying to dereference ("resolve") the future makes us wait for it
+    LLEventWithID value;
+    {
+        // instantiate Suspending to manage "current" coroutine
+        llcoro::Suspending suspended;
+        value = *future;
+    } // destroy Suspending as soon as we're back
+    LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << name
+                             << " resuming with (" << value.first << ", " << value.second << ")"
+                             << LL_ENDL;
+    // returning should disconnect both connections
+    return value;
+}
+
 LLSD errorException(const LLEventWithID& result, const std::string& desc)
 {
     // If the result arrived on the error pump (pump 1), instead of
@@ -144,3 +318,5 @@ LLSD errorLog(const LLEventWithID& result, const std::string& desc)
     // A simple return must therefore be from the reply pump (pump 0).
     return result.first;
 }
+
+} // namespace llcoro
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index abbeeaa3739d8ef2ae3ce04b88a3f1976fc71044..6fda3d2572e9b2941b17f34e7160e20302b6b812 100755
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -29,8 +29,6 @@
 #if ! defined(LL_LLEVENTCORO_H)
 #define LL_LLEVENTCORO_H
 
-#include <boost/dcoroutine/coroutine.hpp>
-#include <boost/dcoroutine/future.hpp>
 #include <boost/optional.hpp>
 #include <string>
 #include <stdexcept>
@@ -74,13 +72,16 @@ class LLEventPumpOrPumpName
     boost::optional<LLEventPump&> mPump;
 };
 
+namespace llcoro
+{
+
 /// This is an adapter for a signature like void LISTENER(const LLSD&), which
 /// isn't a valid LLEventPump listener: such listeners should return bool.
 template <typename LISTENER>
-class LLVoidListener
+class VoidListener
 {
 public:
-    LLVoidListener(const LISTENER& listener):
+    VoidListener(const LISTENER& listener):
         mListener(listener)
     {}
     bool operator()(const LLSD& event)
@@ -93,92 +94,45 @@ class LLVoidListener
     LISTENER mListener;
 };
 
-/// LLVoidListener helper function to infer the type of the LISTENER
+/// VoidListener helper function to infer the type of the LISTENER
 template <typename LISTENER>
-LLVoidListener<LISTENER> voidlistener(const LISTENER& listener)
+VoidListener<LISTENER> voidlistener(const LISTENER& listener)
 {
-    return LLVoidListener<LISTENER>(listener);
+    return VoidListener<LISTENER>(listener);
 }
 
-namespace LLEventDetail
-{
-    /// Implementation for listenerNameForCoro(), see below
-    LL_COMMON_API std::string listenerNameForCoroImpl(const void* self_id);
-
-    /**
-     * waitForEventOn() permits a coroutine to temporarily listen on an
-     * LLEventPump any number of times. We don't really want to have to ask
-     * the caller to label each such call with a distinct string; the whole
-     * point of waitForEventOn() is to present a nice sequential interface to
-     * the underlying LLEventPump-with-named-listeners machinery. So we'll use
-     * LLEventPump::inventName() to generate a distinct name for each
-     * temporary listener. On the other hand, because a given coroutine might
-     * call waitForEventOn() any number of times, we don't really want to
-     * consume an arbitrary number of generated inventName()s: that namespace,
-     * though large, is nonetheless finite. So we memoize an invented name for
-     * each distinct coroutine instance (each different 'self' object). We
-     * can't know the type of 'self', because it depends on the coroutine
-     * body's signature. So we cast its address to void*, looking for distinct
-     * pointer values. Yes, that means that an early coroutine could cache a
-     * value here, then be destroyed, only to be supplanted by a later
-     * coroutine (of the same or different type), and we'll end up
-     * "recognizing" the second one and reusing the listener name -- but
-     * that's okay, since it won't collide with any listener name used by the
-     * earlier coroutine since that earlier coroutine no longer exists.
-     */
-    template <typename COROUTINE_SELF>
-    std::string listenerNameForCoro(COROUTINE_SELF& self)
-    {
-        return listenerNameForCoroImpl(self.get_id());
-    }
-
-    /**
-     * Implement behavior described for postAndWait()'s @a replyPumpNamePath
-     * parameter:
-     *
-     * * If <tt>path.isUndefined()</tt>, do nothing.
-     * * If <tt>path.isString()</tt>, @a dest is an LLSD map: store @a value
-     *   into <tt>dest[path.asString()]</tt>.
-     * * If <tt>path.isInteger()</tt>, @a dest is an LLSD array: store @a
-     *   value into <tt>dest[path.asInteger()]</tt>.
-     * * If <tt>path.isArray()</tt>, iteratively apply the rules above to step
-     *   down through the structure of @a dest. The last array entry in @a
-     *   path specifies the entry in the lowest-level structure in @a dest
-     *   into which to store @a value.
-     *
-     * @note
-     * In the degenerate case in which @a path is an empty array, @a dest will
-     * @em become @a value rather than @em containing it.
-     */
-    LL_COMMON_API void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value);
-} // namespace LLEventDetail
+/**
+ * Yield control from a coroutine for one "mainloop" tick. If your coroutine
+ * runs without suspending for nontrivial time, sprinkle in calls to this
+ * function to avoid stalling the rest of the viewer processing.
+ */
+void suspend();
 
 /**
- * Post specified LLSD event on the specified LLEventPump, then wait for a
+ * Post specified LLSD event on the specified LLEventPump, then suspend for a
  * response on specified other LLEventPump. This is more than mere
  * convenience: the difference between this function and the sequence
  * @code
  * requestPump.post(myEvent);
- * LLSD reply = waitForEventOn(self, replyPump);
+ * LLSD reply = suspendUntilEventOn(replyPump);
  * @endcode
  * is that the sequence above fails if the reply is posted immediately on
  * @a replyPump, that is, before <tt>requestPump.post()</tt> returns. In the
  * sequence above, the running coroutine isn't even listening on @a replyPump
- * until <tt>requestPump.post()</tt> returns and @c waitForEventOn() is
+ * until <tt>requestPump.post()</tt> returns and @c suspendUntilEventOn() is
  * entered. Therefore, the coroutine completely misses an immediate reply
- * event, making it wait indefinitely.
+ * event, making it suspend indefinitely.
  *
- * By contrast, postAndWait() listens on the @a replyPump @em before posting
+ * By contrast, postAndSuspend() listens on the @a replyPump @em before posting
  * the specified LLSD event on the specified @a requestPump.
  *
- * @param self The @c self object passed into a coroutine
  * @param event LLSD data to be posted on @a requestPump
  * @param requestPump an LLEventPump on which to post @a event. Pass either
  * the LLEventPump& or its string name. However, if you pass a
  * default-constructed @c LLEventPumpOrPumpName, we skip the post() call.
- * @param replyPump an LLEventPump on which postAndWait() will listen for a
+ * @param replyPump an LLEventPump on which postAndSuspend() will listen for a
  * reply. Pass either the LLEventPump& or its string name. The calling
- * coroutine will wait until that reply arrives. (If you're concerned about a
+ * coroutine will suspend until that reply arrives. (If you're concerned about a
  * reply that might not arrive, please see also LLEventTimeout.)
  * @param replyPumpNamePath specifies the location within @a event in which to
  * store <tt>replyPump.getName()</tt>. This is a strictly optional convenience
@@ -201,101 +155,29 @@ namespace LLEventDetail
  *   @a replyPumpNamePath specifies the entry in the lowest-level structure in
  *   @a event into which to store <tt>replyPump.getName()</tt>.
  */
-template <typename SELF>
-LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
-                 const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD())
-{
-    // declare the future
-    boost::dcoroutines::future<LLSD> future(self);
-    // make a callback that will assign a value to the future, and listen on
-    // the specified LLEventPump with that callback
-    std::string listenerName(LLEventDetail::listenerNameForCoro(self));
-    LLTempBoundListener connection(
-        replyPump.getPump().listen(listenerName,
-                                   voidlistener(boost::dcoroutines::make_callback(future))));
-    // skip the "post" part if requestPump is default-constructed
-    if (requestPump)
-    {
-        // If replyPumpNamePath is non-empty, store the replyPump name in the
-        // request event.
-        LLSD modevent(event);
-        LLEventDetail::storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName());
-		LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
-                                 << " posting to " << requestPump.getPump().getName()
-								 << LL_ENDL;
-
-		// *NOTE:Mani - Removed because modevent could contain user's hashed passwd.
-		//                         << ": " << modevent << LL_ENDL;
-        requestPump.getPump().post(modevent);
-    }
-    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
-                             << " about to wait on LLEventPump " << replyPump.getPump().getName()
-                             << LL_ENDL;
-    // trying to dereference ("resolve") the future makes us wait for it
-    LLSD value(*future);
-    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
-                             << " resuming with " << value << LL_ENDL;
-    // returning should disconnect the connection
-    return value;
-}
+LLSD postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+                 const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD());
 
 /// Wait for the next event on the specified LLEventPump. Pass either the
 /// LLEventPump& or its string name.
-template <typename SELF>
-LLSD waitForEventOn(SELF& self, const LLEventPumpOrPumpName& pump)
+inline
+LLSD suspendUntilEventOn(const LLEventPumpOrPumpName& pump)
 {
-    // This is now a convenience wrapper for postAndWait().
-    return postAndWait(self, LLSD(), LLEventPumpOrPumpName(), pump);
+    // This is now a convenience wrapper for postAndSuspend().
+    return postAndSuspend(LLSD(), LLEventPumpOrPumpName(), pump);
 }
 
-/// return type for two-pump variant of waitForEventOn()
+} // namespace llcoro
+
+/// return type for two-pump variant of suspendUntilEventOn()
 typedef std::pair<LLSD, int> LLEventWithID;
 
-namespace LLEventDetail
+namespace llcoro
 {
-    /**
-     * This helper is specifically for the two-pump version of waitForEventOn().
-     * We use a single future object, but we want to listen on two pumps with it.
-     * Since we must still adapt from (the callable constructed by)
-     * boost::dcoroutines::make_callback() (void return) to provide an event
-     * listener (bool return), we've adapted LLVoidListener for the purpose. The
-     * basic idea is that we construct a distinct instance of WaitForEventOnHelper
-     * -- binding different instance data -- for each of the pumps. Then, when a
-     * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine
-     * that LLSD with its discriminator to feed the future object.
-     */
-    template <typename LISTENER>
-    class WaitForEventOnHelper
-    {
-    public:
-        WaitForEventOnHelper(const LISTENER& listener, int discriminator):
-            mListener(listener),
-            mDiscrim(discriminator)
-        {}
-        // this signature is required for an LLEventPump listener
-        bool operator()(const LLSD& event)
-        {
-            // our future object is defined to accept LLEventWithID
-            mListener(LLEventWithID(event, mDiscrim));
-            // don't swallow the event, let other listeners see it
-            return false;
-        }
-    private:
-        LISTENER mListener;
-        const int mDiscrim;
-    };
-
-    /// WaitForEventOnHelper type-inference helper
-    template <typename LISTENER>
-    WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator)
-    {
-        return WaitForEventOnHelper<LISTENER>(listener, discriminator);
-    }
-} // namespace LLEventDetail
 
 /**
  * This function waits for a reply on either of two specified LLEventPumps.
- * Otherwise, it closely resembles postAndWait(); please see the documentation
+ * Otherwise, it closely resembles postAndSuspend(); please see the documentation
  * for that function for detailed parameter info.
  *
  * While we could have implemented the single-pump variant in terms of this
@@ -310,81 +192,41 @@ namespace LLEventDetail
  * the index of the pump on which it arrived (0 or 1).
  *
  * @note
- * I'd have preferred to overload the name postAndWait() for both signatures.
+ * I'd have preferred to overload the name postAndSuspend() for both signatures.
  * But consider the following ambiguous call:
  * @code
- * postAndWait(self, LLSD(), requestPump, replyPump, "someString");
+ * postAndSuspend(LLSD(), requestPump, replyPump, "someString");
  * @endcode
  * "someString" could be converted to either LLSD (@a replyPumpNamePath for
  * the single-pump function) or LLEventOrPumpName (@a replyPump1 for two-pump
  * function).
  *
- * It seems less burdensome to write postAndWait2() than to write either
+ * It seems less burdensome to write postAndSuspend2() than to write either
  * LLSD("someString") or LLEventOrPumpName("someString").
  */
-template <typename SELF>
-LLEventWithID postAndWait2(SELF& self, const LLSD& event,
+LLEventWithID postAndSuspend2(const LLSD& event,
                            const LLEventPumpOrPumpName& requestPump,
                            const LLEventPumpOrPumpName& replyPump0,
                            const LLEventPumpOrPumpName& replyPump1,
                            const LLSD& replyPump0NamePath=LLSD(),
-                           const LLSD& replyPump1NamePath=LLSD())
-{
-    // declare the future
-    boost::dcoroutines::future<LLEventWithID> future(self);
-    // either callback will assign a value to this future; listen on
-    // each specified LLEventPump with a callback
-    std::string name(LLEventDetail::listenerNameForCoro(self));
-    LLTempBoundListener connection0(
-        replyPump0.getPump().listen(name + "a",
-                               LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 0)));
-    LLTempBoundListener connection1(
-        replyPump1.getPump().listen(name + "b",
-                               LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 1)));
-    // skip the "post" part if requestPump is default-constructed
-    if (requestPump)
-    {
-        // If either replyPumpNamePath is non-empty, store the corresponding
-        // replyPump name in the request event.
-        LLSD modevent(event);
-        LLEventDetail::storeToLLSDPath(modevent, replyPump0NamePath,
-                                       replyPump0.getPump().getName());
-        LLEventDetail::storeToLLSDPath(modevent, replyPump1NamePath,
-                                       replyPump1.getPump().getName());
-        LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
-                                 << " posting to " << requestPump.getPump().getName()
-                                 << ": " << modevent << LL_ENDL;
-        requestPump.getPump().post(modevent);
-    }
-    LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
-                             << " about to wait on LLEventPumps " << replyPump0.getPump().getName()
-                             << ", " << replyPump1.getPump().getName() << LL_ENDL;
-    // trying to dereference ("resolve") the future makes us wait for it
-    LLEventWithID value(*future);
-    LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name
-                             << " resuming with (" << value.first << ", " << value.second << ")"
-                             << LL_ENDL;
-    // returning should disconnect both connections
-    return value;
-}
+                           const LLSD& replyPump1NamePath=LLSD());
 
 /**
  * Wait for the next event on either of two specified LLEventPumps.
  */
-template <typename SELF>
+inline
 LLEventWithID
-waitForEventOn(SELF& self,
-               const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
+suspendUntilEventOn(const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
 {
-    // This is now a convenience wrapper for postAndWait2().
-    return postAndWait2(self, LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
+    // This is now a convenience wrapper for postAndSuspend2().
+    return postAndSuspend2(LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
 }
 
 /**
- * Helper for the two-pump variant of waitForEventOn(), e.g.:
+ * Helper for the two-pump variant of suspendUntilEventOn(), e.g.:
  *
  * @code
- * LLSD reply = errorException(waitForEventOn(self, replyPump, errorPump),
+ * LLSD reply = errorException(suspendUntilEventOn(replyPump, errorPump),
  *                             "error response from login.cgi");
  * @endcode
  *
@@ -400,6 +242,8 @@ waitForEventOn(SELF& self,
  */
 LLSD errorException(const LLEventWithID& result, const std::string& desc);
 
+} // namespace llcoro
+
 /**
  * Exception thrown by errorException(). We don't call this LLEventError
  * because it's not an error in event processing: rather, this exception
@@ -420,12 +264,17 @@ class LL_COMMON_API LLErrorEvent: public std::runtime_error
     LLSD mData;
 };
 
+namespace llcoro
+{
+
 /**
  * Like errorException(), save that this trips a fatal error using LL_ERRS
  * rather than throwing an exception.
  */
 LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc);
 
+} // namespace llcoro
+
 /**
  * Certain event APIs require the name of an LLEventPump on which they should
  * post results. While it works to invent a distinct name and let
@@ -437,7 +286,7 @@ LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc
  * 2. Provide its actual name to the event API in question as the name of the
  *    reply LLEventPump.
  * 3. Initiate the request to the event API.
- * 4. Call your LLEventTempStream's wait() method to wait for the reply.
+ * 4. Call your LLEventTempStream's suspend() method to suspend for the reply.
  * 5. Let the LLCoroEventPump go out of scope.
  */
 class LL_COMMON_API LLCoroEventPump
@@ -454,26 +303,16 @@ class LL_COMMON_API LLCoroEventPump
 
     /**
      * Wait for an event on this LLEventPump.
-     *
-     * @note
-     * The other major usage pattern we considered was to bind @c self at
-     * LLCoroEventPump construction time, which would avoid passing the
-     * parameter to each wait() call. But if we were going to bind @c self as
-     * a class member, we'd need to specify a class template parameter
-     * indicating its type. The big advantage of passing it to the wait() call
-     * is that the type can be implicit.
      */
-    template <typename SELF>
-    LLSD wait(SELF& self)
+    LLSD suspend()
     {
-        return waitForEventOn(self, mPump);
+        return llcoro::suspendUntilEventOn(mPump);
     }
 
-    template <typename SELF>
-    LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+    LLSD postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
                      const LLSD& replyPumpNamePath=LLSD())
     {
-        return ::postAndWait(self, event, requestPump, mPump, replyPumpNamePath);
+        return llcoro::postAndSuspend(event, requestPump, mPump, replyPumpNamePath);
     }
 
 private:
@@ -509,57 +348,51 @@ class LL_COMMON_API LLCoroEventPumps
     /// request pump 1
     LLEventPump& getPump1() { return mPump1; }
 
-    /// waitForEventOn(self, either of our two LLEventPumps)
-    template <typename SELF>
-    LLEventWithID wait(SELF& self)
+    /// suspendUntilEventOn(either of our two LLEventPumps)
+    LLEventWithID suspend()
     {
-        return waitForEventOn(self, mPump0, mPump1);
+        return llcoro::suspendUntilEventOn(mPump0, mPump1);
     }
 
-    /// errorException(wait(self))
-    template <typename SELF>
-    LLSD waitWithException(SELF& self)
+    /// errorException(suspend())
+    LLSD suspendWithException()
     {
-        return errorException(wait(self), std::string("Error event on ") + getName1());
+        return llcoro::errorException(suspend(), std::string("Error event on ") + getName1());
     }
 
-    /// errorLog(wait(self))
-    template <typename SELF>
-    LLSD waitWithLog(SELF& self)
+    /// errorLog(suspend())
+    LLSD suspendWithLog()
     {
-        return errorLog(wait(self), std::string("Error event on ") + getName1());
+        return llcoro::errorLog(suspend(), std::string("Error event on ") + getName1());
     }
 
-    template <typename SELF>
-    LLEventWithID postAndWait(SELF& self, const LLSD& event,
+    LLEventWithID postAndSuspend(const LLSD& event,
                               const LLEventPumpOrPumpName& requestPump,
                               const LLSD& replyPump0NamePath=LLSD(),
                               const LLSD& replyPump1NamePath=LLSD())
     {
-        return postAndWait2(self, event, requestPump, mPump0, mPump1,
-                            replyPump0NamePath, replyPump1NamePath);
+        return llcoro::postAndSuspend2(event, requestPump, mPump0, mPump1,
+                                    replyPump0NamePath, replyPump1NamePath);
     }
 
-    template <typename SELF>
-    LLSD postAndWaitWithException(SELF& self, const LLSD& event,
+    LLSD postAndSuspendWithException(const LLSD& event,
                                   const LLEventPumpOrPumpName& requestPump,
                                   const LLSD& replyPump0NamePath=LLSD(),
                                   const LLSD& replyPump1NamePath=LLSD())
     {
-        return errorException(postAndWait(self, event, requestPump,
-                                          replyPump0NamePath, replyPump1NamePath),
-                              std::string("Error event on ") + getName1());
+        return llcoro::errorException(postAndSuspend(event, requestPump,
+                                                  replyPump0NamePath, replyPump1NamePath),
+                                      std::string("Error event on ") + getName1());
     }
 
-    template <typename SELF>
-    LLSD postAndWaitWithLog(SELF& self, const LLSD& event,
+    LLSD postAndSuspendWithLog(const LLSD& event,
                             const LLEventPumpOrPumpName& requestPump,
                             const LLSD& replyPump0NamePath=LLSD(),
                             const LLSD& replyPump1NamePath=LLSD())
     {
-        return errorLog(postAndWait(self, event, requestPump,
-                                    replyPump0NamePath, replyPump1NamePath),
-                        std::string("Error event on ") + getName1());
+        return llcoro::errorLog(postAndSuspend(event, requestPump,
+                                            replyPump0NamePath, replyPump1NamePath),
+                                std::string("Error event on ") + getName1());
     }
 
 private:
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index c4c9cc0566151cd3e15d9482a904eb76dfc64c63..d3a9bbc4ae2f2f3e5afe7a77a08b3cbdc61c0c71 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -28,6 +28,7 @@
 
 #include "linden_common.h"
 #include "llunits.h"
+#include "stdtypes.h"
 #if !LL_WINDOWS
 #include <stdint.h>
 #endif
@@ -59,7 +60,7 @@ class LLMutex ;
 LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
 
 #ifdef SHOW_ASSERT
-#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
+#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(uintptr_t(ptr),((U32)alignment))
 #else
 #define ll_assert_aligned(ptr,alignment)
 #endif
@@ -69,13 +70,13 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
 template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) 
 { 
 	return reinterpret_cast<T*>(
-		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
+		(uintptr_t(address) + 0xF) & ~0xF);
 }
 
 template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) 
 { 
 	return reinterpret_cast<T*>(
-		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
+		(uintptr_t(address) + 0x3F) & ~0x3F);
 }
 
 #if LL_LINUX || LL_DARWIN
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 3659a319a2efd3e90d267a800ac05e24950ce901..ea535cee86d1783be719df606b9dea747694e7cd 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -33,6 +33,10 @@
 
 #define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
 
+#if MUTEX_DEBUG
+#include <map>
+#endif
+
 struct apr_thread_mutex_t;
 struct apr_pool_t;
 struct apr_thread_cond_t;
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index e0aa30cc1a22586cb43debb0ed07a857aa95e714..44f56daf2dec5f6b96774dca026fcd90bd0d051a 100755
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -710,7 +710,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
 
 		// Tie the lifespan of this child process to the lifespan of our APR
 		// pool: on destruction of the pool, forcibly kill the process. Tell
-		// APR to try SIGTERM and wait 3 seconds. If that didn't work, use
+		// APR to try SIGTERM and suspend 3 seconds. If that didn't work, use
 		// SIGKILL.
 		apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT);
 |*==========================================================================*/
@@ -989,9 +989,9 @@ void LLProcess::handle_status(int reason, int status)
 //	wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
 	// It's just wrong to call apr_proc_wait() here. The only way APR knows to
 	// call us with APR_OC_REASON_DEATH is that it's already reaped this child
-	// process, so calling wait() will only produce "huh?" from the OS. We
+	// process, so calling suspend() will only produce "huh?" from the OS. We
 	// must rely on the status param passed in, which unfortunately comes
-	// straight from the OS wait() call, which means we have to decode it by
+	// straight from the OS suspend() call, which means we have to decode it by
 	// hand.
 	mStatus = interpret_status(status);
 	LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 3836a9b5fbe85555ec8afde55fa0b3755d0d82c8..11079735691b58be85916e4e34db789d456d8cb8 100755
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -143,15 +143,10 @@ class LL_COMMON_API LLThreadSafeRefCount
 	LLAtomic32< S32	> mRef; 
 };
 
-/**
- * intrusive pointer support
- * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
- */
 /**
  * intrusive pointer support for LLThreadSafeRefCount
  * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
  */
-
 inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) 
 {
 	p->ref();
@@ -162,6 +157,10 @@ inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
 	p->unref(); 
 }
 
+/**
+ * intrusive pointer support
+ * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
+ */
 inline void intrusive_ptr_add_ref(LLRefCount* p) 
 {
 	p->ref();
diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8caaaee53460adc7fe214e29982ba607eaaaabe7
--- /dev/null
+++ b/indra/llcommon/llsdjson.cpp
@@ -0,0 +1,126 @@
+/** 
+ * @file llsdjson.cpp
+ * @brief LLSD flexible data system
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Must turn on conditional declarations in header file so definitions end up
+// with proper linkage.
+#define LLSD_DEBUG_INFO
+#include "linden_common.h"
+
+#include "llsdjson.h"
+
+#include "llerror.h"
+#include "../llmath/llmath.h"
+
+//=========================================================================
+LLSD LlsdFromJson(const Json::Value &val)
+{
+    LLSD result;
+
+    switch (val.type())
+    {
+    default:
+    case Json::nullValue:
+        break;
+    case Json::intValue:
+        result = LLSD(static_cast<LLSD::Integer>(val.asInt()));
+        break;
+    case Json::uintValue:
+        result = LLSD(static_cast<LLSD::Integer>(val.asUInt()));
+        break;
+    case Json::realValue:
+        result = LLSD(static_cast<LLSD::Real>(val.asDouble()));
+        break;
+    case Json::stringValue:
+        result = LLSD(static_cast<LLSD::String>(val.asString()));
+        break;
+    case Json::booleanValue:
+        result = LLSD(static_cast<LLSD::Boolean>(val.asBool()));
+        break;
+    case Json::arrayValue:
+        result = LLSD::emptyArray();
+        for (Json::ValueConstIterator it = val.begin(); it != val.end(); ++it)
+        {
+            result.append(LlsdFromJson((*it)));
+        }
+        break;
+    case Json::objectValue:
+        result = LLSD::emptyMap();
+        for (Json::ValueConstIterator it = val.begin(); it != val.end(); ++it)
+        {
+            result[it.memberName()] = LlsdFromJson((*it));
+        }
+        break;
+    }
+    return result;
+}
+
+//=========================================================================
+Json::Value LlsdToJson(const LLSD &val)
+{
+    Json::Value result;
+
+    switch (val.type())
+    {
+    case LLSD::TypeUndefined:
+        result = Json::Value::null;
+        break;
+    case LLSD::TypeBoolean:
+        result = Json::Value(static_cast<bool>(val.asBoolean()));
+        break;
+    case LLSD::TypeInteger:
+        result = Json::Value(static_cast<int>(val.asInteger()));
+        break;
+    case LLSD::TypeReal:
+        result = Json::Value(static_cast<double>(val.asReal()));
+        break;
+    case LLSD::TypeURI:
+    case LLSD::TypeDate:
+    case LLSD::TypeUUID:
+    case LLSD::TypeString:
+        result = Json::Value(val.asString());
+        break;
+    case LLSD::TypeMap:
+        result = Json::Value(Json::objectValue);
+        for (LLSD::map_const_iterator it = val.beginMap(); it != val.endMap(); ++it)
+        {
+            result[it->first] = LlsdToJson(it->second);
+        }
+        break;
+    case LLSD::TypeArray:
+        result = Json::Value(Json::arrayValue);
+        for (LLSD::array_const_iterator it = val.beginArray(); it != val.endArray(); ++it)
+        {
+            result.append(LlsdToJson(*it));
+        }
+        break;
+    case LLSD::TypeBinary:
+    default:
+        LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL;
+        break;
+    }
+
+    return result;
+}
diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h
new file mode 100644
index 0000000000000000000000000000000000000000..2be711240487c9d1c878f07f887161cf7c85b04a
--- /dev/null
+++ b/indra/llcommon/llsdjson.h
@@ -0,0 +1,77 @@
+/** 
+ * @file llsdjson.cpp
+ * @brief LLSD flexible data system
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDJSON_H
+#define LL_LLSDJSON_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "stdtypes.h"
+
+#include "llsd.h"
+#include "value.h"
+
+/// Convert a parsed JSON structure into LLSD maintaining member names and 
+/// array indexes.
+/// JSON/JavaScript types are converted as follows:
+/// 
+/// JSON Type     | LLSD Type
+/// --------------+--------------
+///  null         |  undefined
+///  integer      |  LLSD::Integer
+///  unsigned     |  LLSD::Integer
+///  real/numeric |  LLSD::Real
+///  string       |  LLSD::String
+///  boolean      |  LLSD::Boolean
+///  array        |  LLSD::Array
+///  object       |  LLSD::Map
+///  
+/// For maps and arrays child entries will be converted and added to the structure.
+/// Order is preserved for an array but not for objects.
+LLSD LlsdFromJson(const Json::Value &val);
+
+/// Convert an LLSD object into Parsed JSON object maintaining member names and 
+/// array indexs.
+/// 
+/// Types are converted as follows:
+/// LLSD Type     |  JSON Type
+/// --------------+----------------
+/// TypeUndefined | null
+/// TypeBoolean   | boolean
+/// TypeInteger   | integer
+/// TypeReal      | real/numeric
+/// TypeString    | string
+/// TypeURI       | string
+/// TypeDate      | string
+/// TypeUUID      | string
+/// TypeMap       | object
+/// TypeArray     | array
+/// TypeBinary    | unsupported 
+Json::Value LlsdToJson(const LLSD &val);
+
+#endif // LL_LLSDJSON_H
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 02f10fa2ba470d19ed5b743fa327438e970954bf..0435cb8a08d9515afda8ea2316719b86822c2234 100755
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -27,6 +27,7 @@
 #ifndef LL_LLSTL_H
 #define LL_LLSTL_H
 
+#include "stdtypes.h"
 #include <functional>
 #include <algorithm>
 #include <map>
@@ -272,6 +273,7 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
 	}
 };
 
+// Useful for replacing the removeObj() functionality of LLDynamicArray
 // Example:
 //  for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); )
 //  {
@@ -530,7 +532,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs)
     return strcmp(lhs->name(), rhs->name()) < 0;
 #else  // not Linux, or gcc 4.4+
     // Just use before(), as we normally would
-    return lhs->before(*rhs);
+    return lhs->before(*rhs) ? true : false;
 #endif
 }
 
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 0177f48bf5d08a722abb8de1f72c34bb9a3714fc..393f6d7a8c1534ef0c796079c04f7136d8fb1bcd 100755
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -1394,6 +1394,7 @@ BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string)
 	return rv;
 }
 
+// *TODO: reimplement in terms of algorithm 
 //static
 template<class T> 
 void LLStringUtilBase<T>::stripNonprintable(string_type& string)
@@ -1427,6 +1428,7 @@ void LLStringUtilBase<T>::stripNonprintable(string_type& string)
 	delete []c_string;
 }
 
+// *TODO: reimplement in terms of algorithm 
 template<class T>
 std::basic_string<T> LLStringUtilBase<T>::quote(const string_type& str,
 												const string_type& triggers,
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 2096807e53effcfc49e5bd288e30f4fe8675f458..1ee79e9eb654cb6e3bf427d9f48933b54399994d 100755
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -59,17 +59,20 @@
 //  http://www.boost.org/LICENSE_1_0.txt)
 /*****************************************************************************/
 
+#define BOOST_RESULT_OF_USE_TR1 1
 // On some platforms, Boost.Coroutine must #define magic symbols before
 // #including platform-API headers. Naturally, that's ineffective unless the
 // Boost.Coroutine #include is the *first* #include of the platform header.
 // That means that client code must generally #include Boost.Coroutine headers
 // before anything else.
+#define BOOST_RESULT_OF_USE_TR1 1
 #include <boost/dcoroutine/coroutine.hpp>
 // Normally, lleventcoro.h obviates future.hpp. We only include this because
 // we implement a "by hand" test of future functionality.
 #include <boost/dcoroutine/future.hpp>
 #include <boost/bind.hpp>
 #include <boost/range.hpp>
+#include <boost/utility.hpp>
 
 #include "linden_common.h"
 
@@ -82,9 +85,12 @@
 #include "llevents.h"
 #include "tests/wrapllerrs.h"
 #include "stringize.h"
+#include "llcoros.h"
 #include "lleventcoro.h"
 #include "../test/debug.h"
 
+using namespace llcoro;
+
 /*****************************************************************************
 *   from the banana.cpp example program borrowed for test<1>()
 *****************************************************************************/
@@ -121,13 +127,10 @@ typedef coroutine<std::string::iterator(void)> match_coroutine_type;
 /*****************************************************************************
 *   Test helpers
 *****************************************************************************/
-// I suspect this will be typical of coroutines used in Linden software
-typedef boost::dcoroutines::coroutine<void()> coroutine_type;
-
 /// Simulate an event API whose response is immediate: sent on receipt of the
 /// initial request, rather than after some delay. This is the case that
-/// distinguishes postAndWait() from calling post(), then calling
-/// waitForEventOn().
+/// distinguishes postAndSuspend() from calling post(), then calling
+/// suspendUntilEventOn().
 class ImmediateAPI
 {
 public:
@@ -162,306 +165,7 @@ class ImmediateAPI
 *****************************************************************************/
 namespace tut
 {
-    struct coroutine_data
-    {
-        // Define coroutine bodies as methods here so they can use ensure*()
-
-        void explicit_wait(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                // ... do whatever preliminary stuff must happen ...
-
-                // declare the future
-                boost::dcoroutines::future<LLSD> future(self);
-                // tell the future what to wait for
-                LLTempBoundListener connection(
-                    LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::dcoroutines::make_callback(future))));
-                ensure("Not yet", ! future);
-                // attempting to dereference ("resolve") the future causes the calling
-                // coroutine to wait for it
-                debug("about to wait");
-                result = *future;
-                ensure("Got it", future);
-            }
-            END
-        }
-
-        void waitForEventOn1(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                result = waitForEventOn(self, "source");
-            }
-            END
-        }
-
-        void waitForEventOn2(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLEventWithID pair = waitForEventOn(self, "reply", "error");
-                result = pair.first;
-                which  = pair.second;
-                debug(STRINGIZE("result = " << result << ", which = " << which));
-            }
-            END
-        }
-
-        void postAndWait1(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                result = postAndWait(self,
-                                     LLSDMap("value", 17),       // request event
-                                     immediateAPI.getPump(),     // requestPump
-                                     "reply1",                   // replyPump
-                                     "reply");                   // request["reply"] = name
-            }
-            END
-        }
-
-        void postAndWait2(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLEventWithID pair = ::postAndWait2(self,
-                                                    LLSDMap("value", 18),
-                                                    immediateAPI.getPump(),
-                                                    "reply2",
-                                                    "error2",
-                                                    "reply",
-                                                    "error");
-                result = pair.first;
-                which  = pair.second;
-                debug(STRINGIZE("result = " << result << ", which = " << which));
-            }
-            END
-        }
-
-        void postAndWait2_1(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLEventWithID pair = ::postAndWait2(self,
-                                                    LLSDMap("value", 18)("fail", LLSD()),
-                                                    immediateAPI.getPump(),
-                                                    "reply2",
-                                                    "error2",
-                                                    "reply",
-                                                    "error");
-                result = pair.first;
-                which  = pair.second;
-                debug(STRINGIZE("result = " << result << ", which = " << which));
-            }
-            END
-        }
-
-        void coroPump(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPump waiter;
-                replyName = waiter.getName();
-                result = waiter.wait(self);
-            }
-            END
-        }
-
-        void coroPumpPost(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPump waiter;
-                result = waiter.postAndWait(self, LLSDMap("value", 17),
-                                            immediateAPI.getPump(), "reply");
-            }
-            END
-        }
-
-        void coroPumps(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                replyName = waiter.getName0();
-                errorName = waiter.getName1();
-                LLEventWithID pair(waiter.wait(self));
-                result = pair.first;
-                which  = pair.second;
-            }
-            END
-        }
-
-        void coroPumpsNoEx(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                replyName = waiter.getName0();
-                errorName = waiter.getName1();
-                result = waiter.waitWithException(self);
-            }
-            END
-        }
-
-        void coroPumpsEx(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                replyName = waiter.getName0();
-                errorName = waiter.getName1();
-                try
-                {
-                    result = waiter.waitWithException(self);
-                    debug("no exception");
-                }
-                catch (const LLErrorEvent& e)
-                {
-                    debug(STRINGIZE("exception " << e.what()));
-                    errordata = e.getData();
-                }
-            }
-            END
-        }
-
-        void coroPumpsNoLog(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                replyName = waiter.getName0();
-                errorName = waiter.getName1();
-                result = waiter.waitWithLog(self);
-            }
-            END
-        }
-
-        void coroPumpsLog(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                replyName = waiter.getName0();
-                errorName = waiter.getName1();
-                WrapLLErrs capture;
-                try
-                {
-                    result = waiter.waitWithLog(self);
-                    debug("no exception");
-                }
-                catch (const WrapLLErrs::FatalException& e)
-                {
-                    debug(STRINGIZE("exception " << e.what()));
-                    threw = e.what();
-                }
-            }
-            END
-        }
-
-        void coroPumpsPost(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                LLEventWithID pair(waiter.postAndWait(self, LLSDMap("value", 23),
-                                                      immediateAPI.getPump(), "reply", "error"));
-                result = pair.first;
-                which  = pair.second;
-            }
-            END
-        }
-
-        void coroPumpsPost_1(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                LLEventWithID pair(
-                    waiter.postAndWait(self, LLSDMap("value", 23)("fail", LLSD()),
-                                       immediateAPI.getPump(), "reply", "error"));
-                result = pair.first;
-                which  = pair.second;
-            }
-            END
-        }
-
-        void coroPumpsPostNoEx(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                result = waiter.postAndWaitWithException(self, LLSDMap("value", 8),
-                                                         immediateAPI.getPump(), "reply", "error");
-            }
-            END
-        }
-
-        void coroPumpsPostEx(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                try
-                {
-                    result = waiter.postAndWaitWithException(self,
-                        LLSDMap("value", 9)("fail", LLSD()),
-                        immediateAPI.getPump(), "reply", "error");
-                    debug("no exception");
-                }
-                catch (const LLErrorEvent& e)
-                {
-                    debug(STRINGIZE("exception " << e.what()));
-                    errordata = e.getData();
-                }
-            }
-            END
-        }
-
-        void coroPumpsPostNoLog(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                result = waiter.postAndWaitWithLog(self, LLSDMap("value", 30),
-                                                   immediateAPI.getPump(), "reply", "error");
-            }
-            END
-        }
-
-        void coroPumpsPostLog(coroutine_type::self& self)
-        {
-            BEGIN
-            {
-                LLCoroEventPumps waiter;
-                WrapLLErrs capture;
-                try
-                {
-                    result = waiter.postAndWaitWithLog(self,
-                        LLSDMap("value", 31)("fail", LLSD()),
-                        immediateAPI.getPump(), "reply", "error");
-                    debug("no exception");
-                }
-                catch (const WrapLLErrs::FatalException& e)
-                {
-                    debug(STRINGIZE("exception " << e.what()));
-                    threw = e.what();
-                }
-            }
-            END
-        }
-
-        void ensure_done(coroutine_type& coro)
-        {
-            ensure("coroutine complete", ! coro);
-        }
-
-        ImmediateAPI immediateAPI;
-        std::string replyName, errorName, threw;
-        LLSD result, errordata;
-        int which;
-    };
+    struct coroutine_data {};
     typedef test_group<coroutine_data> coroutine_group;
     typedef coroutine_group::object object;
     coroutine_group coroutinegrp("coroutine");
@@ -511,54 +215,113 @@ namespace tut
         ensure("done", ! matcher);
     }
 
+    // use static data so we can intersperse coroutine functions with the
+    // tests that engage them
+    ImmediateAPI immediateAPI;
+    std::string replyName, errorName, threw;
+    LLSD result, errordata;
+    int which;
+
+    // reinit vars at the start of each test
+    void clear()
+    {
+        replyName.clear();
+        errorName.clear();
+        threw.clear();
+        result = LLSD();
+        errordata = LLSD();
+        which = 0;
+    }
+
+    void explicit_wait(boost::dcoroutines::coroutine<void()>::self& self)
+    {
+        BEGIN
+        {
+            // ... do whatever preliminary stuff must happen ...
+
+            // declare the future
+            boost::dcoroutines::future<LLSD> future(self);
+            // tell the future what to suspend for
+            LLTempBoundListener connection(
+                LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::dcoroutines::make_callback(future))));
+            ensure("Not yet", ! future);
+            // attempting to dereference ("resolve") the future causes the calling
+            // coroutine to suspend for it
+            debug("about to suspend");
+            result = *future;
+            ensure("Got it", future);
+        }
+        END
+    }
+
     template<> template<>
     void object::test<2>()
     {
+        clear();
         set_test_name("explicit_wait");
         DEBUG;
 
         // Construct the coroutine instance that will run explicit_wait.
         // Pass the ctor a callable that accepts the coroutine_type::self
         // param passed by the library.
-        coroutine_type coro(boost::bind(&coroutine_data::explicit_wait, this, _1));
+        boost::dcoroutines::coroutine<void()> coro(explicit_wait);
         // Start the coroutine
         coro(std::nothrow);
         // When the coroutine waits for the event pump, it returns here.
         debug("about to send");
-        // Satisfy the wait.
+        // Satisfy the suspend.
         LLEventPumps::instance().obtain("source").post("received");
-        // Now wait for the coroutine to complete.
-        ensure_done(coro);
+        // Now suspend for the coroutine to complete.
+        ensure("coroutine complete", ! coro);
         // ensure the coroutine ran and woke up again with the intended result
         ensure_equals(result.asString(), "received");
     }
 
+    void waitForEventOn1()
+    {
+        BEGIN
+        {
+            result = suspendUntilEventOn("source");
+        }
+        END
+    }
+
     template<> template<>
     void object::test<3>()
     {
+        clear();
         set_test_name("waitForEventOn1");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn1, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<3>", waitForEventOn1);
         debug("about to send");
         LLEventPumps::instance().obtain("source").post("received");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "received");
     }
 
+    void waitForEventOn2()
+    {
+        BEGIN
+        {
+            LLEventWithID pair = suspendUntilEventOn("reply", "error");
+            result = pair.first;
+            which  = pair.second;
+            debug(STRINGIZE("result = " << result << ", which = " << which));
+        }
+        END
+    }
+
     template<> template<>
     void object::test<4>()
     {
+        clear();
         set_test_name("waitForEventOn2 reply");
         {
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<4>", waitForEventOn2);
         debug("about to send");
         LLEventPumps::instance().obtain("reply").post("received");
         debug("back from send");
-        ensure_done(coro);
         }
         ensure_equals(result.asString(), "received");
         ensure_equals("which pump", which, 0);
@@ -567,43 +330,65 @@ namespace tut
     template<> template<>
     void object::test<5>()
     {
+        clear();
         set_test_name("waitForEventOn2 error");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::waitForEventOn2, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<5>", waitForEventOn2);
         debug("about to send");
         LLEventPumps::instance().obtain("error").post("badness");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "badness");
         ensure_equals("which pump", which, 1);
     }
 
+    void coroPump()
+    {
+        BEGIN
+        {
+            LLCoroEventPump waiter;
+            replyName = waiter.getName();
+            result = waiter.suspend();
+        }
+        END
+    }
+
     template<> template<>
     void object::test<6>()
     {
+        clear();
         set_test_name("coroPump");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPump, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<6>", coroPump);
         debug("about to send");
         LLEventPumps::instance().obtain(replyName).post("received");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "received");
     }
 
+    void coroPumps()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            replyName = waiter.getName0();
+            errorName = waiter.getName1();
+            LLEventWithID pair(waiter.suspend());
+            result = pair.first;
+            which  = pair.second;
+        }
+        END
+    }
+
     template<> template<>
     void object::test<7>()
     {
+        clear();
         set_test_name("coroPumps reply");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<7>", coroPumps);
         debug("about to send");
         LLEventPumps::instance().obtain(replyName).post("received");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "received");
         ensure_equals("which pump", which, 0);
     }
@@ -611,188 +396,389 @@ namespace tut
     template<> template<>
     void object::test<8>()
     {
+        clear();
         set_test_name("coroPumps error");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumps, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<8>", coroPumps);
         debug("about to send");
         LLEventPumps::instance().obtain(errorName).post("badness");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "badness");
         ensure_equals("which pump", which, 1);
     }
 
+    void coroPumpsNoEx()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            replyName = waiter.getName0();
+            errorName = waiter.getName1();
+            result = waiter.suspendWithException();
+        }
+        END
+    }
+
     template<> template<>
     void object::test<9>()
     {
+        clear();
         set_test_name("coroPumpsNoEx");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoEx, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<9>", coroPumpsNoEx);
         debug("about to send");
         LLEventPumps::instance().obtain(replyName).post("received");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "received");
     }
 
+    void coroPumpsEx()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            replyName = waiter.getName0();
+            errorName = waiter.getName1();
+            try
+            {
+                result = waiter.suspendWithException();
+                debug("no exception");
+            }
+            catch (const LLErrorEvent& e)
+            {
+                debug(STRINGIZE("exception " << e.what()));
+                errordata = e.getData();
+            }
+        }
+        END
+    }
+
     template<> template<>
     void object::test<10>()
     {
+        clear();
         set_test_name("coroPumpsEx");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsEx, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<10>", coroPumpsEx);
         debug("about to send");
         LLEventPumps::instance().obtain(errorName).post("badness");
         debug("back from send");
-        ensure_done(coro);
         ensure("no result", result.isUndefined());
         ensure_equals("got error", errordata.asString(), "badness");
     }
 
+    void coroPumpsNoLog()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            replyName = waiter.getName0();
+            errorName = waiter.getName1();
+            result = waiter.suspendWithLog();
+        }
+        END
+    }
+
     template<> template<>
     void object::test<11>()
     {
+        clear();
         set_test_name("coroPumpsNoLog");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsNoLog, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<11>", coroPumpsNoLog);
         debug("about to send");
         LLEventPumps::instance().obtain(replyName).post("received");
         debug("back from send");
-        ensure_done(coro);
         ensure_equals(result.asString(), "received");
     }
 
+    void coroPumpsLog()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            replyName = waiter.getName0();
+            errorName = waiter.getName1();
+            WrapLLErrs capture;
+            try
+            {
+                result = waiter.suspendWithLog();
+                debug("no exception");
+            }
+            catch (const WrapLLErrs::FatalException& e)
+            {
+                debug(STRINGIZE("exception " << e.what()));
+                threw = e.what();
+            }
+        }
+        END
+    }
+
     template<> template<>
     void object::test<12>()
     {
+        clear();
         set_test_name("coroPumpsLog");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsLog, this, _1));
-        coro(std::nothrow);
+        LLCoros::instance().launch("test<12>", coroPumpsLog);
         debug("about to send");
         LLEventPumps::instance().obtain(errorName).post("badness");
         debug("back from send");
-        ensure_done(coro);
         ensure("no result", result.isUndefined());
         ensure_contains("got error", threw, "badness");
     }
 
+    void postAndWait1()
+    {
+        BEGIN
+        {
+            result = postAndSuspend(LLSDMap("value", 17),       // request event
+                                 immediateAPI.getPump(),     // requestPump
+                                 "reply1",                   // replyPump
+                                 "reply");                   // request["reply"] = name
+        }
+        END
+    }
+
     template<> template<>
     void object::test<13>()
     {
+        clear();
         set_test_name("postAndWait1");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::postAndWait1, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<13>", postAndWait1);
         ensure_equals(result.asInteger(), 18);
     }
 
+    void postAndWait2()
+    {
+        BEGIN
+        {
+            LLEventWithID pair = ::postAndSuspend2(LLSDMap("value", 18),
+                                                immediateAPI.getPump(),
+                                                "reply2",
+                                                "error2",
+                                                "reply",
+                                                "error");
+            result = pair.first;
+            which  = pair.second;
+            debug(STRINGIZE("result = " << result << ", which = " << which));
+        }
+        END
+    }
+
     template<> template<>
     void object::test<14>()
     {
+        clear();
         set_test_name("postAndWait2");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::postAndWait2, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<14>", postAndWait2);
         ensure_equals(result.asInteger(), 19);
         ensure_equals(which, 0);
     }
 
+    void postAndWait2_1()
+    {
+        BEGIN
+        {
+            LLEventWithID pair = ::postAndSuspend2(LLSDMap("value", 18)("fail", LLSD()),
+                                                immediateAPI.getPump(),
+                                                "reply2",
+                                                "error2",
+                                                "reply",
+                                                "error");
+            result = pair.first;
+            which  = pair.second;
+            debug(STRINGIZE("result = " << result << ", which = " << which));
+        }
+        END
+    }
+
     template<> template<>
     void object::test<15>()
     {
+        clear();
         set_test_name("postAndWait2_1");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::postAndWait2_1, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<15>", postAndWait2_1);
         ensure_equals(result.asInteger(), 19);
         ensure_equals(which, 1);
     }
 
+    void coroPumpPost()
+    {
+        BEGIN
+        {
+            LLCoroEventPump waiter;
+            result = waiter.postAndSuspend(LLSDMap("value", 17),
+                                        immediateAPI.getPump(), "reply");
+        }
+        END
+    }
+
     template<> template<>
     void object::test<16>()
     {
+        clear();
         set_test_name("coroPumpPost");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpPost, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<16>", coroPumpPost);
         ensure_equals(result.asInteger(), 18);
     }
 
+    void coroPumpsPost()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            LLEventWithID pair(waiter.postAndSuspend(LLSDMap("value", 23),
+                                                  immediateAPI.getPump(), "reply", "error"));
+            result = pair.first;
+            which  = pair.second;
+        }
+        END
+    }
+
     template<> template<>
     void object::test<17>()
     {
+        clear();
         set_test_name("coroPumpsPost reply");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<17>", coroPumpsPost);
         ensure_equals(result.asInteger(), 24);
         ensure_equals("which pump", which, 0);
     }
 
+    void coroPumpsPost_1()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            LLEventWithID pair(
+                waiter.postAndSuspend(LLSDMap("value", 23)("fail", LLSD()),
+                                   immediateAPI.getPump(), "reply", "error"));
+            result = pair.first;
+            which  = pair.second;
+        }
+        END
+    }
+
     template<> template<>
     void object::test<18>()
     {
+        clear();
         set_test_name("coroPumpsPost error");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPost_1, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<18>", coroPumpsPost_1);
         ensure_equals(result.asInteger(), 24);
         ensure_equals("which pump", which, 1);
     }
 
+    void coroPumpsPostNoEx()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            result = waiter.postAndSuspendWithException(LLSDMap("value", 8),
+                                                     immediateAPI.getPump(), "reply", "error");
+        }
+        END
+    }
+
     template<> template<>
     void object::test<19>()
     {
+        clear();
         set_test_name("coroPumpsPostNoEx");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoEx, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<19>", coroPumpsPostNoEx);
         ensure_equals(result.asInteger(), 9);
     }
 
+    void coroPumpsPostEx()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            try
+            {
+                result = waiter.postAndSuspendWithException(
+                    LLSDMap("value", 9)("fail", LLSD()),
+                    immediateAPI.getPump(), "reply", "error");
+                debug("no exception");
+            }
+            catch (const LLErrorEvent& e)
+            {
+                debug(STRINGIZE("exception " << e.what()));
+                errordata = e.getData();
+            }
+        }
+        END
+    }
+
     template<> template<>
     void object::test<20>()
     {
+        clear();
         set_test_name("coroPumpsPostEx");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostEx, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<20>", coroPumpsPostEx);
         ensure("no result", result.isUndefined());
         ensure_equals("got error", errordata.asInteger(), 10);
     }
 
+    void coroPumpsPostNoLog()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            result = waiter.postAndSuspendWithLog(LLSDMap("value", 30),
+                                               immediateAPI.getPump(), "reply", "error");
+        }
+        END
+    }
+
     template<> template<>
     void object::test<21>()
     {
+        clear();
         set_test_name("coroPumpsPostNoLog");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostNoLog, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<21>", coroPumpsPostNoLog);
         ensure_equals(result.asInteger(), 31);
     }
 
+    void coroPumpsPostLog()
+    {
+        BEGIN
+        {
+            LLCoroEventPumps waiter;
+            WrapLLErrs capture;
+            try
+            {
+                result = waiter.postAndSuspendWithLog(
+                    LLSDMap("value", 31)("fail", LLSD()),
+                    immediateAPI.getPump(), "reply", "error");
+                debug("no exception");
+            }
+            catch (const WrapLLErrs::FatalException& e)
+            {
+                debug(STRINGIZE("exception " << e.what()));
+                threw = e.what();
+            }
+        }
+        END
+    }
+
     template<> template<>
     void object::test<22>()
     {
+        clear();
         set_test_name("coroPumpsPostLog");
         DEBUG;
-        coroutine_type coro(boost::bind(&coroutine_data::coroPumpsPostLog, this, _1));
-        coro(std::nothrow);
-        ensure_done(coro);
+        LLCoros::instance().launch("test<22>", coroPumpsPostLog);
         ensure("no result", result.isUndefined());
         ensure_contains("got error", threw, "32");
     }
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index a0b1ea13b1f6237526d3edb816be451b53cccbe5..4aecf61bd7a3df07b3f56f4db029bf666cf5c3da 100755
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -5,7 +5,6 @@ project(llcorehttp)
 include(00-Common)
 include(GoogleMock)
 include(CURL)
-include(CARes)
 include(OpenSSL)
 include(ZLIB)
 include(LLCoreHttp)
@@ -26,6 +25,7 @@ set(llcorehttp_SOURCE_FILES
     bufferarray.cpp
     bufferstream.cpp
     httpcommon.cpp
+    llhttpconstants.cpp
     httpheaders.cpp
     httpoptions.cpp
     httprequest.cpp
@@ -51,6 +51,7 @@ set(llcorehttp_HEADER_FILES
     bufferarray.h
     bufferstream.h
     httpcommon.h
+    llhttpconstants.h
     httphandler.h
     httpheaders.h
     httpoptions.h
@@ -89,7 +90,6 @@ add_library (llcorehttp ${llcorehttp_SOURCE_FILES})
 target_link_libraries(
   llcorehttp
   ${CURL_LIBRARIES}
-  ${CARES_LIBRARIES}
   ${OPENSSL_LIBRARIES}
   ${CRYPTO_LIBRARIES}
   ${BOOST_THREAD_LIBRARY}
@@ -127,16 +127,19 @@ if (LL_TESTS)
       ${LLCOMMON_LIBRARIES}
       ${GOOGLEMOCK_LIBRARIES}
       ${CURL_LIBRARIES}
-      ${CARES_LIBRARIES}
       ${OPENSSL_LIBRARIES}
       ${CRYPTO_LIBRARIES}
       ${BOOST_SYSTEM_LIBRARY}
       ${BOOST_THREAD_LIBRARY}
       )
 
+  # If http_proxy is in the current environment (e.g. to fetch s3-proxy
+  # autobuild packages), suppress it for this integration test: it screws up
+  # the tests.
   LL_ADD_INTEGRATION_TEST(llcorehttp
                           "${llcorehttp_TEST_SOURCE_FILES}"
                           "${test_libs}"
+                          "-Dhttp_proxy"
                           ${PYTHON_EXECUTABLE}
                           "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llcorehttp_peer.py"
                           )
@@ -155,7 +158,6 @@ if (LL_TESTS)
       ${LLCOMMON_LIBRARIES}
       ${GOOGLEMOCK_LIBRARIES}
       ${CURL_LIBRARIES}
-      ${CARES_LIBRARIES}
       ${OPENSSL_LIBRARIES}
       ${CRYPTO_LIBRARIES}
       ${BOOST_SYSTEM_LIBRARY}
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index a2a60ca05677eb5d611b04789b7b5e01ed30b540..79c89d6c920f9950ca8171bf81c6cd6cfc58e37b 100755
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -104,8 +104,9 @@ namespace LLCore
 {
 
 // Maxium number of policy classes that can be defined.
-// *TODO:  Currently limited to the default class + 1, extend.
-const int HTTP_POLICY_CLASS_LIMIT = 8;
+// *TODO:  Currently limited to the default class + 1, extend. 
+// (TSN: should this be more dynamically sized.  Is there a reason to hard limit the number of policies?)
+const int HTTP_POLICY_CLASS_LIMIT = 32;
 
 // Debug/informational tracing.  Used both
 // as a global option and in per-request traces.
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 81b44ab90b56667afcad5ee029e8261d38633f34..17e997688fa5117c876c450bfa3a4948766a70ee 100755
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -554,7 +554,7 @@ void HttpLibcurl::HandleCache::freeHandle(CURL * handle)
 // ---------------------------------------
 
 
-struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct curl_slist * slist)
+struct curl_slist * append_headers_to_slist(const HttpHeaders::ptr_t &headers, struct curl_slist * slist)
 {
 	const HttpHeaders::const_iterator end(headers->end());
 	for (HttpHeaders::const_iterator it(headers->begin()); end != it; ++it)
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index b9632a7921a23ca1869f6da5cd11061ee32cace6..86110f5b46cc2f0117d907248f1da9e22a009ef2 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -122,8 +122,8 @@ HttpOpRequest::HttpOpRequest()
 	  mReqBody(NULL),
 	  mReqOffset(0),
 	  mReqLength(0),
-	  mReqHeaders(NULL),
-	  mReqOptions(NULL),
+	  mReqHeaders(),
+	  mReqOptions(),
 	  mCurlActive(false),
 	  mCurlHandle(NULL),
 	  mCurlService(NULL),
@@ -135,11 +135,12 @@ HttpOpRequest::HttpOpRequest()
 	  mReplyOffset(0),
 	  mReplyLength(0),
 	  mReplyFullLength(0),
-	  mReplyHeaders(NULL),
+	  mReplyHeaders(),
 	  mPolicyRetries(0),
 	  mPolicy503Retries(0),
 	  mPolicyRetryAt(HttpTime(0)),
-	  mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT)
+	  mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT),
+	  mCallbackSSLVerify(NULL)
 {
 	// *NOTE:  As members are added, retry initialization/cleanup
 	// may need to be extended in @see prepareRequest().
@@ -155,18 +156,6 @@ HttpOpRequest::~HttpOpRequest()
 		mReqBody = NULL;
 	}
 	
-	if (mReqOptions)
-	{
-		mReqOptions->release();
-		mReqOptions = NULL;
-	}
-
-	if (mReqHeaders)
-	{
-		mReqHeaders->release();
-		mReqHeaders = NULL;
-	}
-
 	if (mCurlHandle)
 	{
 		// Uncertain of thread context so free using
@@ -193,11 +182,6 @@ HttpOpRequest::~HttpOpRequest()
 		mReplyBody = NULL;
 	}
 
-	if (mReplyHeaders)
-	{
-		mReplyHeaders->release();
-		mReplyHeaders = NULL;
-	}
 }
 
 
@@ -259,7 +243,9 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
 		response->setStatus(mStatus);
 		response->setBody(mReplyBody);
 		response->setHeaders(mReplyHeaders);
-		if (mReplyOffset || mReplyLength)
+        response->setRequestURL(mReqURL);
+
+        if (mReplyOffset || mReplyLength)
 		{
 			// Got an explicit offset/length in response
 			response->setRange(mReplyOffset, mReplyLength, mReplyFullLength);
@@ -267,6 +253,14 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
 		response->setContentType(mReplyConType);
 		response->setRetries(mPolicyRetries, mPolicy503Retries);
 		
+		HttpResponse::TransferStats::ptr_t stats = HttpResponse::TransferStats::ptr_t(new HttpResponse::TransferStats);
+
+		curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &stats->mSizeDownload);
+		curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &stats->mTotalTime);
+		curl_easy_getinfo(mCurlHandle, CURLINFO_SPEED_DOWNLOAD, &stats->mSpeedDownload);
+
+		response->setTransferStats(stats);
+
 		mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
 
 		response->release();
@@ -287,8 +281,8 @@ HttpStatus HttpOpRequest::cancel()
 HttpStatus HttpOpRequest::setupGet(HttpRequest::policy_t policy_id,
 								   HttpRequest::priority_t priority,
 								   const std::string & url,
-								   HttpOptions * options,
-								   HttpHeaders * headers)
+                                   const HttpOptions::ptr_t & options,
+								   const HttpHeaders::ptr_t & headers)
 {
 	setupCommon(policy_id, priority, url, NULL, options, headers);
 	mReqMethod = HOR_GET;
@@ -302,8 +296,8 @@ HttpStatus HttpOpRequest::setupGetByteRange(HttpRequest::policy_t policy_id,
 											const std::string & url,
 											size_t offset,
 											size_t len,
-											HttpOptions * options,
-											HttpHeaders * headers)
+                                            const HttpOptions::ptr_t & options,
+                                            const HttpHeaders::ptr_t & headers)
 {
 	setupCommon(policy_id, priority, url, NULL, options, headers);
 	mReqMethod = HOR_GET;
@@ -322,8 +316,8 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
 									HttpRequest::priority_t priority,
 									const std::string & url,
 									BufferArray * body,
-									HttpOptions * options,
-									HttpHeaders * headers)
+                                    const HttpOptions::ptr_t & options,
+                                    const HttpHeaders::ptr_t & headers)
 {
 	setupCommon(policy_id, priority, url, body, options, headers);
 	mReqMethod = HOR_POST;
@@ -336,8 +330,8 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
 								   HttpRequest::priority_t priority,
 								   const std::string & url,
 								   BufferArray * body,
-								   HttpOptions * options,
-								   HttpHeaders * headers)
+                                   const HttpOptions::ptr_t & options,
+								   const HttpHeaders::ptr_t & headers)
 {
 	setupCommon(policy_id, priority, url, body, options, headers);
 	mReqMethod = HOR_PUT;
@@ -346,12 +340,65 @@ HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
 }
 
 
+HttpStatus HttpOpRequest::setupDelete(HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers)
+{
+    setupCommon(policy_id, priority, url, NULL, options, headers);
+    mReqMethod = HOR_DELETE;
+
+    return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupPatch(HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    BufferArray * body,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers)
+{
+    setupCommon(policy_id, priority, url, body, options, headers);
+    mReqMethod = HOR_PATCH;
+
+    return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupCopy(HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t &headers)
+{
+    setupCommon(policy_id, priority, url, NULL, options, headers);
+    mReqMethod = HOR_COPY;
+
+    return HttpStatus();
+}
+
+
+HttpStatus HttpOpRequest::setupMove(HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t &headers)
+{
+    setupCommon(policy_id, priority, url, NULL, options, headers);
+    mReqMethod = HOR_MOVE;
+
+    return HttpStatus();
+}
+
+
 void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
 								HttpRequest::priority_t priority,
 								const std::string & url,
 								BufferArray * body,
-								HttpOptions * options,
-								HttpHeaders * headers)
+                                const HttpOptions::ptr_t & options,
+								const HttpHeaders::ptr_t & headers)
 {
 	mProcFlags = 0U;
 	mReqPolicy = policy_id;
@@ -364,12 +411,10 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
 	}
 	if (headers && ! mReqHeaders)
 	{
-		headers->addRef();
 		mReqHeaders = headers;
 	}
-	if (options && ! mReqOptions)
+	if (options && !mReqOptions)
 	{
-		options->addRef();
 		mReqOptions = options;
 		if (options->getWantHeaders())
 		{
@@ -416,11 +461,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	mReplyOffset = 0;
 	mReplyLength = 0;
 	mReplyFullLength = 0;
-	if (mReplyHeaders)
-	{
-		mReplyHeaders->release();
-		mReplyHeaders = NULL;
-	}
+    mReplyHeaders.reset();
 	mReplyConType.clear();
 	
 	// *FIXME:  better error handling later
@@ -452,18 +493,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
 	check_curl_easy_code(code, CURLOPT_ENCODING);
 
-	// The Linksys WRT54G V5 router has an issue with frequent
-	// DNS lookups from LAN machines.  If they happen too often,
-	// like for every HTTP request, the router gets annoyed after
-	// about 700 or so requests and starts issuing TCP RSTs to
-	// new connections.  Reuse the DNS lookups for even a few
-	// seconds and no RSTs.
-	code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
-	check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
 	check_curl_easy_code(code, CURLOPT_AUTOREFERER);
-	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
-	check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
 	check_curl_easy_code(code, CURLOPT_MAXREDIRS);
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
@@ -474,11 +505,57 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	check_curl_easy_code(code, CURLOPT_READFUNCTION);
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
 	check_curl_easy_code(code, CURLOPT_READDATA);
-	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
+    code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback);
+    check_curl_easy_code(code, CURLOPT_SEEKFUNCTION);
+    code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, this);
+    check_curl_easy_code(code, CURLOPT_SEEKDATA);
+
+	code = curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, "");
+	check_curl_easy_code(code, CURLOPT_COOKIEFILE);
+
+	if (gpolicy.mSslCtxCallback)
+	{
+		code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback);
+		check_curl_easy_code(code, CURLOPT_SSL_CTX_FUNCTION);
+		code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, this);
+		check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA);
+		mCallbackSSLVerify = gpolicy.mSslCtxCallback;
+	}
+
+	long follow_redirect(1L);
+	long sslPeerV(0L);
+	long sslHostV(0L);
+    long dnsCacheTimeout(-1L);
+    long nobody(0L);
+
+	if (mReqOptions)
+	{
+		follow_redirect = mReqOptions->getFollowRedirects() ? 1L : 0L;
+		sslPeerV = mReqOptions->getSSLVerifyPeer() ? 1L : 0L;
+		sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;
+		dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
+        nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
+	}
+	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
+	check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
+
+	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV);
 	check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER);
-	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);
 	check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
 
+    code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
+    check_curl_easy_code(code, CURLOPT_NOBODY);
+
+	// The Linksys WRT54G V5 router has an issue with frequent
+	// DNS lookups from LAN machines.  If they happen too often,
+	// like for every HTTP request, the router gets annoyed after
+	// about 700 or so requests and starts issuing TCP RSTs to
+	// new connections.  Reuse the DNS lookups for even a few
+	// seconds and no RSTs.
+	code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
+	check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
+
 	if (gpolicy.mUseLLProxy)
 	{
 		// Use the viewer-based thread-safe API which has a
@@ -509,10 +586,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	switch (mReqMethod)
 	{
 	case HOR_GET:
-		code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+        if (nobody == 0)
+            code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
 		check_curl_easy_code(code, CURLOPT_HTTPGET);
-		mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
-		mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
 		break;
 		
 	case HOR_POST:
@@ -531,12 +607,14 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
 			check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE);
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
-			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
-			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
 		}
 		break;
 		
-	case HOR_PUT:
+    case HOR_PATCH:
+        code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
+        check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+        // fall through.  The rest is the same as PUT
+    case HOR_PUT:
 		{
 			code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
 			check_curl_easy_code(code, CURLOPT_UPLOAD);
@@ -547,15 +625,25 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 			}
 			code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
 			check_curl_easy_code(code, CURLOPT_INFILESIZE);
-			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
-			check_curl_easy_code(code, CURLOPT_POSTFIELDS);
 			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
-			// *TODO: Should this be 'Keep-Alive' ?
-			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
-			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
 		}
 		break;
 		
+    case HOR_DELETE:
+        code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+        check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+        break;
+
+    case HOR_COPY:
+        code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY");
+        check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+        break;
+
+    case HOR_MOVE:
+        code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE");
+        check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
+        break;
+
 	default:
 		LL_ERRS(LOG_CORE) << "Invalid HTTP method in request:  "
 						  << int(mReqMethod)  << ".  Can't recover."
@@ -563,6 +651,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 		break;
 	}
 
+
+    // *TODO: Should this be 'Keep-Alive' ?
+    mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
+    mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
+
 	// Tracing
 	if (mTracing >= HTTP_TRACE_CURL_HEADERS)
 	{
@@ -723,6 +816,37 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
 	return read_size;
 }
 
+
+int HttpOpRequest::seekCallback(void *userdata, curl_off_t offset, int origin)
+{
+    HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+
+    if (!op->mReqBody)
+    {
+        return 0;
+    }
+
+    size_t newPos = 0;
+    if (origin == SEEK_SET)
+        newPos = offset;
+    else if (origin == SEEK_END)
+        newPos = static_cast<curl_off_t>(op->mReqBody->size()) + offset;
+    else if (origin == SEEK_CUR)
+        newPos = static_cast<curl_off_t>(op->mCurlBodyPos) + offset;
+    else
+        return 2;
+
+    if (newPos >= op->mReqBody->size())
+    {
+        LL_WARNS(LOG_CORE) << "Attempt to seek to position outside post body." << LL_ENDL;
+        return 2;
+    }
+
+    op->mCurlBodyPos = (size_t)newPos;
+
+    return 0;
+}
+
 		
 size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, void * userdata)
 {
@@ -817,7 +941,7 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 		// Save headers in response
 		if (! op->mReplyHeaders)
 		{
-			op->mReplyHeaders = new HttpHeaders;
+			op->mReplyHeaders = HttpHeaders::ptr_t(new HttpHeaders);
 		}
 		op->mReplyHeaders->append(name, value ? value : "");
 	}
@@ -873,6 +997,35 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 }
 
 
+CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userdata)
+{
+	HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
+
+	if (op->mCallbackSSLVerify)
+	{
+		SSL_CTX * ctx = (SSL_CTX *)sslctx;
+		// disable any default verification for server certs
+		SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+		// set the verification callback.
+		SSL_CTX_set_cert_verify_callback(ctx, sslCertVerifyCallback, userdata);
+		// the calls are void
+	}
+
+	return CURLE_OK;
+}
+
+int HttpOpRequest::sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
+{
+	HttpOpRequest * op(static_cast<HttpOpRequest *>(param));
+
+	if (op->mCallbackSSLVerify)
+	{
+		op->mStatus = op->mCallbackSSLVerify(op->mReqURL, op->mUserHandler, ctx);
+	}
+
+	return (op->mStatus) ? 1 : 0;
+}
+
 int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffer, size_t len, void * userdata)
 {
 	HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 2f628b5abad58f9fd850a3499d9a5ce71a589d88..1b449a5abccdc33250318061be988fd651afc36d 100755
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -33,19 +33,22 @@
 #include <string>
 #include <curl/curl.h>
 
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+
 #include "httpcommon.h"
 #include "httprequest.h"
 #include "_httpoperation.h"
 #include "_refcounted.h"
 
+#include "httpheaders.h"
+#include "httpoptions.h"
 
 namespace LLCore
 {
 
 
 class BufferArray;
-class HttpHeaders;
-class HttpOptions;
 
 
 /// HttpOpRequest requests a supported HTTP method invocation with
@@ -77,7 +80,11 @@ class HttpOpRequest : public HttpOperation
 	{
 		HOR_GET,
 		HOR_POST,
-		HOR_PUT
+		HOR_PUT,
+        HOR_DELETE,
+        HOR_PATCH,
+        HOR_COPY,
+        HOR_MOVE
 	};
 	
 	virtual void stageFromRequest(HttpService *);
@@ -98,32 +105,57 @@ class HttpOpRequest : public HttpOperation
 	HttpStatus setupGet(HttpRequest::policy_t policy_id,
 						HttpRequest::priority_t priority,
 						const std::string & url,
-						HttpOptions * options,
-						HttpHeaders * headers);
+						const HttpOptions::ptr_t & options,
+						const HttpHeaders::ptr_t & headers);
 	
 	HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id,
 								 HttpRequest::priority_t priority,
 								 const std::string & url,
 								 size_t offset,
 								 size_t len,
-								 HttpOptions * options,
-								 HttpHeaders * headers);
+                                 const HttpOptions::ptr_t & options,
+								 const HttpHeaders::ptr_t & headers);
 	
 	HttpStatus setupPost(HttpRequest::policy_t policy_id,
 						 HttpRequest::priority_t priority,
 						 const std::string & url,
 						 BufferArray * body,
-						 HttpOptions * options,
-						 HttpHeaders * headers);
+                         const HttpOptions::ptr_t & options,
+						 const HttpHeaders::ptr_t & headers);
 	
 	HttpStatus setupPut(HttpRequest::policy_t policy_id,
 						HttpRequest::priority_t priority,
 						const std::string & url,
 						BufferArray * body,
-						HttpOptions * options,
-						HttpHeaders * headers);
+                        const HttpOptions::ptr_t & options,
+						const HttpHeaders::ptr_t & headers);
+
+    HttpStatus setupDelete(HttpRequest::policy_t policy_id,
+                        HttpRequest::priority_t priority,
+                        const std::string & url,
+                        const HttpOptions::ptr_t & options,
+                        const HttpHeaders::ptr_t & headers);
+
+    HttpStatus setupPatch(HttpRequest::policy_t policy_id,
+                        HttpRequest::priority_t priority,
+                        const std::string & url,
+                        BufferArray * body,
+                        const HttpOptions::ptr_t & options,
+                        const HttpHeaders::ptr_t & headers);
+
+    HttpStatus setupCopy(HttpRequest::policy_t policy_id,
+                        HttpRequest::priority_t priority,
+                        const std::string & url,
+                        const HttpOptions::ptr_t & options,
+                        const HttpHeaders::ptr_t & headers);
 
-	// Internal method used to setup the libcurl options for a request.
+    HttpStatus setupMove(HttpRequest::policy_t policy_id,
+                        HttpRequest::priority_t priority,
+                        const std::string & url,
+                        const HttpOptions::ptr_t & options,
+                        const HttpHeaders::ptr_t & headers);
+
+    // Internal method used to setup the libcurl options for a request.
 	// Does all the libcurl handle setup in one place.
 	//
 	// Threading:  called by worker thread
@@ -141,8 +173,8 @@ class HttpOpRequest : public HttpOperation
 					 HttpRequest::priority_t priority,
 					 const std::string & url,
 					 BufferArray * body,
-					 HttpOptions * options,
-					 HttpHeaders * headers);
+                     const HttpOptions::ptr_t & options,
+					 const HttpHeaders::ptr_t & headers);
 
 	// libcurl operational callbacks
 	//
@@ -150,7 +182,11 @@ class HttpOpRequest : public HttpOperation
 	//
 	static size_t writeCallback(void * data, size_t size, size_t nmemb, void * userdata);
 	static size_t readCallback(void * data, size_t size, size_t nmemb, void * userdata);
+    static int seekCallback(void *data, curl_off_t offset, int origin);
 	static size_t headerCallback(void * data, size_t size, size_t nmemb, void * userdata);
+	static CURLcode curlSslCtxCallback(CURL *curl, void *ssl_ctx, void *userptr);
+	static int sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
+
 	static int debugCallback(CURL *, curl_infotype info, char * buffer, size_t len, void * userdata);
 
 protected:
@@ -159,6 +195,8 @@ class HttpOpRequest : public HttpOperation
 	static const unsigned int	PF_SAVE_HEADERS = 0x00000002U;
 	static const unsigned int	PF_USE_RETRY_AFTER = 0x00000004U;
 
+	HttpRequest::policyCallback_t	mCallbackSSLVerify;
+
 public:
 	// Request data
 	EMethod				mReqMethod;
@@ -166,8 +204,8 @@ class HttpOpRequest : public HttpOperation
 	BufferArray *		mReqBody;
 	off_t				mReqOffset;
 	size_t				mReqLength;
-	HttpHeaders *		mReqHeaders;
-	HttpOptions *		mReqOptions;
+	HttpHeaders::ptr_t	mReqHeaders;
+    HttpOptions::ptr_t  mReqOptions;
 
 	// Transport data
 	bool				mCurlActive;
@@ -184,7 +222,7 @@ class HttpOpRequest : public HttpOperation
 	off_t				mReplyOffset;
 	size_t				mReplyLength;
 	size_t				mReplyFullLength;
-	HttpHeaders *		mReplyHeaders;
+	HttpHeaders::ptr_t	mReplyHeaders;
 	std::string			mReplyConType;
 	int					mReplyRetryAfter;
 
@@ -215,7 +253,7 @@ class HttpOpRequestCompare
 
 // Internal function to append the contents of an HttpHeaders
 // instance to a curl_slist object.
-curl_slist * append_headers_to_slist(const HttpHeaders *, curl_slist * slist);
+curl_slist * append_headers_to_slist(const HttpHeaders::ptr_t &, curl_slist * slist);
 
 }   // end namespace LLCore
 
diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp
index 1dc95f3dce113ec9542f8fc6556320aa0fc45973..3d0df96ade3067b3f3353949ad6e765d4f478c0b 100755
--- a/indra/llcorehttp/_httppolicyglobal.cpp
+++ b/indra/llcorehttp/_httppolicyglobal.cpp
@@ -106,6 +106,20 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, const std::stri
 	return HttpStatus();
 }
 
+HttpStatus HttpPolicyGlobal::set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value)
+{
+	switch (opt)
+	{
+	case HttpRequest::PO_SSL_VERIFY_CALLBACK:
+		mSslCtxCallback = value;
+		break;
+
+	default:
+		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
+	}
+
+	return HttpStatus();
+}
 
 HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, long * value) const
 {
@@ -154,4 +168,20 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, std::string * v
 	return HttpStatus();
 }
 
+
+HttpStatus HttpPolicyGlobal::get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const
+{
+	switch (opt)
+	{
+	case HttpRequest::PO_SSL_VERIFY_CALLBACK:
+		*value = mSslCtxCallback;
+		break;
+
+	default:
+		return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
+	}
+
+	return HttpStatus();
+}
+
 }  // end namespace LLCore
diff --git a/indra/llcorehttp/_httppolicyglobal.h b/indra/llcorehttp/_httppolicyglobal.h
index 67c4ba9481d21b5b4366c106543b75fa6ddbaabe..e02da4386a1c776cd6311e83ee72b1faccde0925 100755
--- a/indra/llcorehttp/_httppolicyglobal.h
+++ b/indra/llcorehttp/_httppolicyglobal.h
@@ -60,8 +60,10 @@ class HttpPolicyGlobal
 public:
 	HttpStatus set(HttpRequest::EPolicyOption opt, long value);
 	HttpStatus set(HttpRequest::EPolicyOption opt, const std::string & value);
+	HttpStatus set(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t value);
 	HttpStatus get(HttpRequest::EPolicyOption opt, long * value) const;
 	HttpStatus get(HttpRequest::EPolicyOption opt, std::string * value) const;
+	HttpStatus get(HttpRequest::EPolicyOption opt, HttpRequest::policyCallback_t * value) const;
 	
 public:
 	long				mConnectionLimit;
@@ -70,6 +72,7 @@ class HttpPolicyGlobal
 	std::string			mHttpProxy;
 	long				mTrace;
 	long				mUseLLProxy;
+	HttpRequest::policyCallback_t	mSslCtxCallback;
 };  // end class HttpPolicyGlobal
 
 }  // end namespace LLCore
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index c673e1be1d316f3e7c85b8f0b7be1c897ef9cac0..252db78c899efaaf98fddaea5bfe392e01b4e9e6 100755
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -53,15 +53,16 @@ namespace LLCore
 
 const HttpService::OptionDescriptor HttpService::sOptionDesc[] =
 { //    isLong     isDynamic  isGlobal    isClass
-	{	true,		true,		true,		true	},		// PO_CONNECTION_LIMIT
-	{	true,		true,		false,		true	},		// PO_PER_HOST_CONNECTION_LIMIT
-	{	false,		false,		true,		false	},		// PO_CA_PATH
-	{	false,		false,		true,		false	},		// PO_CA_FILE
-	{	false,		true,		true,		false	},		// PO_HTTP_PROXY
-	{	true,		true,		true,		false	},		// PO_LLPROXY
-	{	true,		true,		true,		false	},		// PO_TRACE
-	{	true,		true,		false,		true	},		// PO_ENABLE_PIPELINING
-	{	true,		true,		false,		true	}		// PO_THROTTLE_RATE
+	{	true,		true,		true,		true,		false	},		// PO_CONNECTION_LIMIT
+	{	true,		true,		false,		true,		false	},		// PO_PER_HOST_CONNECTION_LIMIT
+	{	false,		false,		true,		false,		false	},		// PO_CA_PATH
+	{	false,		false,		true,		false,		false	},		// PO_CA_FILE
+	{	false,		true,		true,		false,		false	},		// PO_HTTP_PROXY
+	{	true,		true,		true,		false,		false	},		// PO_LLPROXY
+	{	true,		true,		true,		false,		false	},		// PO_TRACE
+	{	true,		true,		false,		true,		false	},		// PO_ENABLE_PIPELINING
+	{	true,		true,		false,		true,		false	},		// PO_THROTTLE_RATE
+	{   false,		false,		true,		false,		true	}		// PO_SSL_VERIFY_CALLBACK
 };
 HttpService * HttpService::sInstance(NULL);
 volatile HttpService::EState HttpService::sState(NOT_INITIALIZED);
@@ -413,6 +414,34 @@ HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
 	return status;
 }
 
+HttpStatus HttpService::getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+	HttpRequest::policyCallback_t * ret_value)
+{
+	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
+
+	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range
+		|| opt >= HttpRequest::PO_LAST													// ditto
+		|| (sOptionDesc[opt].mIsLong)													// datatype is string
+		|| (pclass != HttpRequest::GLOBAL_POLICY_ID && pclass > mLastPolicy)			// pclass in valid range
+		|| (pclass == HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsGlobal)	// global setting permitted
+		|| (pclass != HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsClass))	// class setting permitted
+		// can always get, no dynamic check
+	{
+		return status;
+	}
+
+	// Only global has callback values
+	if (pclass == HttpRequest::GLOBAL_POLICY_ID)
+	{
+		HttpPolicyGlobal & opts(mPolicy->getGlobalOptions());
+
+		status = opts.get(opt, ret_value);
+	}
+
+	return status;
+}
+
+
 
 HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
 										long value, long * ret_value)
@@ -489,6 +518,37 @@ HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequ
 
 	return status;
 }
-	
+
+HttpStatus HttpService::setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t pclass,
+	HttpRequest::policyCallback_t value, HttpRequest::policyCallback_t * ret_value)
+{
+	HttpStatus status(HttpStatus::LLCORE, LLCore::HE_INVALID_ARG);
+
+	if (opt < HttpRequest::PO_CONNECTION_LIMIT											// option must be in range
+		|| opt >= HttpRequest::PO_LAST													// ditto
+		|| (sOptionDesc[opt].mIsLong)													// datatype is string
+		|| (pclass != HttpRequest::GLOBAL_POLICY_ID && pclass > mLastPolicy)			// pclass in valid range
+		|| (pclass == HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsGlobal)	// global setting permitted
+		|| (pclass != HttpRequest::GLOBAL_POLICY_ID && !sOptionDesc[opt].mIsClass)		// class setting permitted
+		|| (RUNNING == sState && !sOptionDesc[opt].mIsDynamic))						// dynamic setting permitted
+	{
+		return status;
+	}
+
+	// Callbacks values are always global (at this time).
+	if (pclass == HttpRequest::GLOBAL_POLICY_ID)
+	{
+		HttpPolicyGlobal & opts(mPolicy->getGlobalOptions());
+
+		status = opts.set(opt, value);
+		if (status && ret_value)
+		{
+			status = opts.get(opt, ret_value);
+		}
+	}
+
+	return status;
+}
+
 
 }  // end namespace LLCore
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index cf23f3ab61f48274d5197daabf2e7f398439eee7..ac518a5de7405022ee270ac6a16b81586b13a56a 100755
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -201,17 +201,24 @@ class HttpService
 		bool		mIsDynamic;
 		bool		mIsGlobal;
 		bool		mIsClass;
+		bool		mIsCallback;
 	};
 		
 	HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
 							   long * ret_value);
 	HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
 							   std::string * ret_value);
+	HttpStatus getPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
+								HttpRequest::policyCallback_t * ret_value);
+
 	HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
 							   long value, long * ret_value);
 	HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
 							   const std::string & value, std::string * ret_value);
-	
+	HttpStatus setPolicyOption(HttpRequest::EPolicyOption opt, HttpRequest::policy_t,
+								HttpRequest::policyCallback_t value, 
+								HttpRequest::policyCallback_t * ret_value);
+
 protected:
 	static const OptionDescriptor		sOptionDesc[HttpRequest::PO_LAST];
 	static HttpService *				sInstance;
diff --git a/indra/llcorehttp/_refcounted.h b/indra/llcorehttp/_refcounted.h
index 402e7251524d1642b5a333b1534a8b49cb35c6aa..7f713f229836a7c2f34ba6ba01a42b850ad315f6 100755
--- a/indra/llcorehttp/_refcounted.h
+++ b/indra/llcorehttp/_refcounted.h
@@ -32,6 +32,7 @@
 
 #include "fix_macros.h"
 #include <boost/thread.hpp>
+#include <boost/intrusive_ptr.hpp>
 
 #include "llapr.h"
 
@@ -120,7 +121,36 @@ inline void RefCounted::destroySelf()
 	delete this;
 }
 
+/**
+ * boost::intrusive_ptr may be used to manage RefCounted classes.
+ * Unfortunately RefCounted and boost::intrusive_ptr use different conventions
+ * for the initial refcount value. To avoid leaky (immortal) objects, you
+ * should really construct boost::intrusive_ptr<RefCounted*>(rawptr, false).
+ * IntrusivePtr<T> encapsulates that for you.
+ */
+template <typename T>
+struct IntrusivePtr: public boost::intrusive_ptr<T>
+{
+	IntrusivePtr():
+		boost::intrusive_ptr<T>()
+	{}
+	IntrusivePtr(T* p):
+		boost::intrusive_ptr<T>(p, false)
+	{}
+};
+
+inline void intrusive_ptr_add_ref(RefCounted* p)
+{
+	p->addRef();
+}
+
+inline void intrusive_ptr_release(RefCounted* p)
+{
+	p->release();
+}
+
 } // end namespace LLCoreInt
 
+
 #endif	// LLCOREINT__REFCOUNTED_H_
 
diff --git a/indra/llcorehttp/bufferarray.h b/indra/llcorehttp/bufferarray.h
index 1094a435b42246a01b4bd93d76211557ea0fd1f3..320adf2b8b5c9a59dfb197f6f542f0eecb12a1e4 100755
--- a/indra/llcorehttp/bufferarray.h
+++ b/indra/llcorehttp/bufferarray.h
@@ -30,6 +30,7 @@
 
 #include <cstdlib>
 #include <vector>
+#include "boost/intrusive_ptr.hpp"
 
 #include "_refcounted.h"
 
@@ -73,6 +74,8 @@ class BufferArray : public LLCoreInt::RefCounted
 	
 	BufferArray();
 
+	typedef LLCoreInt::IntrusivePtr<BufferArray> ptr_t;
+
 protected:
 	virtual ~BufferArray();						// Use release()
 
@@ -129,6 +132,7 @@ class BufferArray : public LLCoreInt::RefCounted
 
 	container_t			mBlocks;
 	size_t				mLen;
+
 };  // end class BufferArray
 
 
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index 9d9631b98078263b7666894b4d190aa04d8f5f82..737282c7dfa1fed232910e9327a07bd4a698eca6 100755
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -83,7 +83,7 @@ class WorkingSet : public LLCore::HttpHandler
 	WorkingSet();
 	~WorkingSet();
 
-	bool reload(LLCore::HttpRequest *, LLCore::HttpOptions *);
+	bool reload(LLCore::HttpRequest *, LLCore::HttpOptions::ptr_t &);
 	
 	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
 
@@ -121,7 +121,7 @@ class WorkingSet : public LLCore::HttpHandler
 	int							mRetriesHttp503;
 	int							mSuccesses;
 	long						mByteCount;
-	LLCore::HttpHeaders *		mHeaders;
+	LLCore::HttpHeaders::ptr_t	mHeaders;
 };
 
 
@@ -304,7 +304,7 @@ int main(int argc, char** argv)
 	LLCore::HttpRequest * hr = new LLCore::HttpRequest();
 
 	// Get request options
-	LLCore::HttpOptions * opt = new LLCore::HttpOptions();
+	LLCore::HttpOptions::ptr_t opt = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
 	opt->setRetries(12);
 	opt->setUseRetryAfter(true);
 	
@@ -363,8 +363,7 @@ int main(int argc, char** argv)
 	// Clean up
 	hr->requestStopThread(NULL);
 	ms_sleep(1000);
-	opt->release();
-	opt = NULL;
+    opt.reset();
 	delete hr;
 	LLCore::HttpRequest::destroyService();
 	term_curl();
@@ -427,22 +426,17 @@ WorkingSet::WorkingSet()
 {
 	mAssets.reserve(30000);
 
-	mHeaders = new LLCore::HttpHeaders;
+	mHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 	mHeaders->append("Accept", "image/x-j2c");
 }
 
 
 WorkingSet::~WorkingSet()
 {
-	if (mHeaders)
-	{
-		mHeaders->release();
-		mHeaders = NULL;
-	}
 }
 
 
-bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions * opt)
+bool WorkingSet::reload(LLCore::HttpRequest * hr, LLCore::HttpOptions::ptr_t & opt)
 {
 	if (mRequestLowWater <= mHandles.size())
 	{
diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index 7907e958a44d0b5a944c0ccbd5bbe777ecf1c2c5..c423047bb08fa6756461e69b5bdbec41f1bafb41 100755
--- a/indra/llcorehttp/httpcommon.cpp
+++ b/indra/llcorehttp/httpcommon.cpp
@@ -23,12 +23,24 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
+#if LL_WINDOWS
+#define SAFE_SSL 1
+#elif LL_DARWIN
+#define SAFE_SSL 1
+#else
+#define SAFE_SSL 1
+#endif
 
+#include "linden_common.h"		// Modifies curl/curl.h interfaces
 #include "httpcommon.h"
-
+#include "llmutex.h"
+#include "llthread.h"
 #include <curl/curl.h>
 #include <string>
 #include <sstream>
+#if SAFE_SSL
+#include <openssl/crypto.h>
+#endif
 
 
 namespace LLCore
@@ -42,7 +54,7 @@ HttpStatus::operator unsigned long() const
 {
 	static const int shift(sizeof(unsigned long) * 4);
 
-	unsigned long result(((unsigned long) mType) << shift | (unsigned long) (int) mStatus);
+	unsigned long result(((unsigned long)mDetails->mType) << shift | (unsigned long)(int)mDetails->mStatus);
 	return result;
 }
 
@@ -131,30 +143,34 @@ std::string HttpStatus::toString() const
 	{
 		return std::string("");
 	}
-	switch (mType)
+	switch (getType())
 	{
 	case EXT_CURL_EASY:
-		return std::string(curl_easy_strerror(CURLcode(mStatus)));
+		return std::string(curl_easy_strerror(CURLcode(getStatus())));
 
 	case EXT_CURL_MULTI:
-		return std::string(curl_multi_strerror(CURLMcode(mStatus)));
+		return std::string(curl_multi_strerror(CURLMcode(getStatus())));
 
 	case LLCORE:
-		if (mStatus >= 0 && mStatus < llcore_errors_count)
+		if (getStatus() >= 0 && getStatus() < llcore_errors_count)
 		{
-			return std::string(llcore_errors[mStatus]);
+			return std::string(llcore_errors[getStatus()]);
 		}
 		break;
 
 	default:
 		if (isHttpStatus())
 		{
+			// special handling for status 499 "Linden Catchall"
+			if ((getType() == 499) && (!getMessage().empty()))
+				return getMessage();
+
 			// Binary search for the error code and string
 			int bottom(0), top(http_errors_count);
 			while (true)
 			{
 				int at((bottom + top) / 2);
-				if (mType == http_errors[at].mCode)
+				if (getType() == http_errors[at].mCode)
 				{
 					return std::string(http_errors[at].mText);
 				}
@@ -162,7 +178,7 @@ std::string HttpStatus::toString() const
 				{
 					break;
 				}
-				else if (mType < http_errors[at].mCode)
+				else if (getType() < http_errors[at].mCode)
 				{
 					top = at;
 				}
@@ -182,9 +198,9 @@ std::string HttpStatus::toTerseString() const
 {
 	std::ostringstream result;
 
-	unsigned int error_value((unsigned short) mStatus);
+	unsigned int error_value((unsigned short)getStatus());
 	
-	switch (mType)
+	switch (getType())
 	{
 	case EXT_CURL_EASY:
 		result << "Easy_";
@@ -202,7 +218,7 @@ std::string HttpStatus::toTerseString() const
 		if (isHttpStatus())
 		{
 			result << "Http_";
-			error_value = mType;
+			error_value = getType();
 		}
 		else
 		{
@@ -244,7 +260,7 @@ bool HttpStatus::isRetryable() const
 	// Disable the '*this == inv_status' test and look for 'Core_9'
 	// failures in log files.
 
-	return ((isHttpStatus() && mType >= 499 && mType <= 599) ||	// Include special 499 in retryables
+	return ((isHttpStatus() && getType() >= 499 && getType() <= 599) ||	// Include special 499 in retryables
 			*this == cant_connect ||	// Connection reset/endpoint problems
 			*this == cant_res_proxy ||	// DNS problems
 			*this == cant_res_host ||	// DNS problems
@@ -259,5 +275,168 @@ bool HttpStatus::isRetryable() const
 			*this == inv_cont_range);	// Short data read disagrees with content-range
 }
 
-} // end namespace LLCore
+namespace LLHttp
+{
+namespace
+{
+typedef boost::shared_ptr<LLMutex> LLMutex_ptr;
+std::vector<LLMutex_ptr> sSSLMutex;
+
+CURL *getCurlTemplateHandle()
+{
+    static CURL *curlpTemplateHandle = NULL;
+
+    if (curlpTemplateHandle == NULL)
+    {	// Late creation of the template curl handle
+        curlpTemplateHandle = curl_easy_init();
+        if (curlpTemplateHandle == NULL)
+        {
+            LL_WARNS() << "curl error calling curl_easy_init()" << LL_ENDL;
+        }
+        else
+        {
+            CURLcode result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+            check_curl_code(result, CURLOPT_IPRESOLVE);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOSIGNAL, 1);
+            check_curl_code(result, CURLOPT_NOSIGNAL);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_NOPROGRESS, 1);
+            check_curl_code(result, CURLOPT_NOPROGRESS);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_ENCODING, "");
+            check_curl_code(result, CURLOPT_ENCODING);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_AUTOREFERER, 1);
+            check_curl_code(result, CURLOPT_AUTOREFERER);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_FOLLOWLOCATION, 1);
+            check_curl_code(result, CURLOPT_FOLLOWLOCATION);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_SSL_VERIFYPEER, 1);
+            check_curl_code(result, CURLOPT_SSL_VERIFYPEER);
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_SSL_VERIFYHOST, 0);
+            check_curl_code(result, CURLOPT_SSL_VERIFYHOST);
+
+            // The Linksys WRT54G V5 router has an issue with frequent
+            // DNS lookups from LAN machines.  If they happen too often,
+            // like for every HTTP request, the router gets annoyed after
+            // about 700 or so requests and starts issuing TCP RSTs to
+            // new connections.  Reuse the DNS lookups for even a few
+            // seconds and no RSTs.
+            result = curl_easy_setopt(curlpTemplateHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
+            check_curl_code(result, CURLOPT_DNS_CACHE_TIMEOUT);
+        }
+    }
+
+    return curlpTemplateHandle;
+}
+    
+LLMutex *getCurlMutex()
+{
+    static LLMutex* sHandleMutexp = NULL;
+
+    if (!sHandleMutexp)
+    {
+        sHandleMutexp = new LLMutex(NULL);
+    }
+
+    return sHandleMutexp;
+}
+
+void deallocateEasyCurl(CURL *curlp)
+{
+    LLMutexLock lock(getCurlMutex());
+
+    curl_easy_cleanup(curlp);
+}
+
+
+#if SAFE_SSL
+//static
+void ssl_locking_callback(int mode, int type, const char *file, int line)
+{
+    if (type >= sSSLMutex.size())
+    {
+        LL_WARNS() << "Attempt to get unknown MUTEX in SSL Lock." << LL_ENDL;
+    }
+
+    if (mode & CRYPTO_LOCK)
+    {
+        sSSLMutex[type]->lock();
+    }
+    else
+    {
+        sSSLMutex[type]->unlock();
+    }
+}
+
+//static
+unsigned long ssl_thread_id(void)
+{
+    return LLThread::currentID();
+}
+#endif
+
 
+}
+
+void initialize()
+{
+    // Do not change this "unless you are familiar with and mean to control 
+    // internal operations of libcurl"
+    // - http://curl.haxx.se/libcurl/c/curl_global_init.html
+    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
+
+    check_curl_code(code, CURL_GLOBAL_ALL);
+
+#if SAFE_SSL
+    S32 mutex_count = CRYPTO_num_locks();
+    for (S32 i = 0; i < mutex_count; i++)
+    {
+        sSSLMutex.push_back(LLMutex_ptr(new LLMutex(NULL)));
+    }
+    CRYPTO_set_id_callback(&ssl_thread_id);
+    CRYPTO_set_locking_callback(&ssl_locking_callback);
+#endif
+
+}
+
+
+void cleanup()
+{
+#if SAFE_SSL
+    CRYPTO_set_id_callback(NULL);
+    CRYPTO_set_locking_callback(NULL);
+    sSSLMutex.clear();
+#endif
+
+    curl_global_cleanup();
+}
+
+
+CURL_ptr createEasyHandle()
+{
+    LLMutexLock lock(getCurlMutex());
+
+    CURL* handle = curl_easy_duphandle(getCurlTemplateHandle());
+
+    return CURL_ptr(handle, &deallocateEasyCurl);
+}
+
+std::string getCURLVersion()
+{
+    return std::string(curl_version());
+}
+
+void check_curl_code(CURLcode code, int curl_setopt_option)
+{
+    if (CURLE_OK != code)
+    {
+        // Comment from old llcurl code which may no longer apply:
+        //
+        // linux appears to throw a curl error once per session for a bad initialization
+        // at a pretty random time (when enabling cookies).
+        LL_WARNS() << "libcurl error detected:  " << curl_easy_strerror(code)
+            << ", curl_easy_setopt option:  " << curl_setopt_option
+            << LL_ENDL;
+    }
+
+}
+
+}
+} // end namespace LLCore
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index 9601f94125f70f4924e1dd11a00c64ea64060458..1bc20fe6b56bd9afe8f894bdf48f2b065ea46785 100755
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -188,9 +188,12 @@
 ///
 
 #include "linden_common.h"		// Modifies curl/curl.h interfaces
-
+#include "boost/intrusive_ptr.hpp"
+#include "boost/shared_ptr.hpp"
+#include "boost/weak_ptr.hpp"
+#include "boost/function.hpp"
 #include <string>
-
+#include <curl/curl.h>
 
 namespace LLCore
 {
@@ -286,52 +289,63 @@ enum HttpError
 /// 5.  Construct an HTTP 301 status code to be treated as success:
 ///				HttpStatus(301, HE_SUCCESS);
 ///
+/// 6.	Construct a failed status of HTTP Status 499 with a custom error message
+///				HttpStatus(499, "Failed LLSD Response");
 
 struct HttpStatus
 {
 	typedef unsigned short type_enum_t;
 	
 	HttpStatus()
-		: mType(LLCORE),
-		  mStatus(HE_SUCCESS)
-		{}
+	{
+		mDetails = boost::shared_ptr<Details>(new Details(LLCORE, HE_SUCCESS));
+    }
 
 	HttpStatus(type_enum_t type, short status)
-		: mType(type),
-		  mStatus(status)
-		{}
+	{
+        mDetails = boost::shared_ptr<Details>(new Details(type, status));
+	}
 	
 	HttpStatus(int http_status)
-		: mType(http_status),
-		  mStatus(http_status >= 200 && http_status <= 299
-				  ? HE_SUCCESS
-				  : HE_REPLY_ERROR)
-		{
-			llassert(http_status >= 100 && http_status <= 999);
-		}
+	{
+        mDetails = boost::shared_ptr<Details>(new Details(http_status, 
+			(http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR));
+		llassert(http_status >= 100 && http_status <= 999);
+	}
+
+	HttpStatus(int http_status, const std::string &message)
+	{
+        mDetails = boost::shared_ptr<Details>(new Details(http_status,
+			(http_status >= 200 && http_status <= 299) ? HE_SUCCESS : HE_REPLY_ERROR));
+		llassert(http_status >= 100 && http_status <= 999);
+		mDetails->mMessage = message;
+	}
 	
 	HttpStatus(const HttpStatus & rhs)
-		: mType(rhs.mType),
-		  mStatus(rhs.mStatus)
-		{}
+	{
+		mDetails = rhs.mDetails;
+	}
+
+	~HttpStatus()
+	{
+	}
 
 	HttpStatus & operator=(const HttpStatus & rhs)
-		{
-			// Don't care if lhs & rhs are the same object
+	{
+        mDetails = rhs.mDetails;
+		return *this;
+	}
 
-			mType = rhs.mType;
-			mStatus = rhs.mStatus;
-			return *this;
-		}
+    HttpStatus & clone(const HttpStatus &rhs)
+    {
+        mDetails = boost::shared_ptr<Details>(new Details(*rhs.mDetails));
+        return *this;
+    }
 	
 	static const type_enum_t EXT_CURL_EASY = 0;			///< mStatus is an error from a curl_easy_*() call
 	static const type_enum_t EXT_CURL_MULTI = 1;		///< mStatus is an error from a curl_multi_*() call
 	static const type_enum_t LLCORE = 2;				///< mStatus is an HE_* error code
 														///< 100-999 directly represent HTTP status codes
-	
-	type_enum_t			mType;
-	short				mStatus;
-
 	/// Test for successful status in the code regardless
 	/// of error source (internal, libcurl).
 	///
@@ -339,7 +353,7 @@ struct HttpStatus
 	///
 	operator bool() const
 	{
-		return 0 == mStatus;
+		return 0 == mDetails->mStatus;
 	}
 
 	/// Inverse of previous operator.
@@ -347,14 +361,14 @@ struct HttpStatus
 	/// @return			'true' on any error condition
 	bool operator !() const
 	{
-		return 0 != mStatus;
+		return 0 != mDetails->mStatus;
 	}
 
 	/// Equality and inequality tests to bypass bool conversion
 	/// which will do the wrong thing in conditional expressions.
 	bool operator==(const HttpStatus & rhs) const
 	{
-		return mType == rhs.mType && mStatus == rhs.mStatus;
+        return (*mDetails == *rhs.mDetails); 
 	}
 
 	bool operator!=(const HttpStatus & rhs) const
@@ -395,7 +409,7 @@ struct HttpStatus
 	/// HTTP response status (100 - 999).
 	bool isHttpStatus() const
 	{
-		return 	mType >= type_enum_t(100) && mType <= type_enum_t(999);
+		return 	mDetails->mType >= type_enum_t(100) && mDetails->mType <= type_enum_t(999);
 	}
 
 	/// Returns true if the status is one that will be retried
@@ -403,9 +417,94 @@ struct HttpStatus
 	/// where that logic needs to be replicated.  Only applies
 	/// to failed statuses, successful statuses will return false.
 	bool isRetryable() const;
-	
+
+	/// Returns the currently set status code as a raw number
+	///
+	short getStatus() const
+	{
+		return mDetails->mStatus;
+	}
+
+	/// Returns the currently set status type 
+	/// 
+	type_enum_t getType() const
+	{
+		return mDetails->mType;
+	}
+
+	/// Returns an optional error message if one has been set.
+	///
+	std::string getMessage() const
+	{
+		return mDetails->mMessage;
+	}
+
+	/// Sets an optional error message
+	/// 
+	void setMessage(const std::string &message)
+	{
+		mDetails->mMessage = message;
+	}
+
+	/// Retrieves an optionally recorded SSL certificate.
+	void * getErrorData() const
+	{
+		return mDetails->mErrorData;
+	}
+
+	/// Optionally sets an SSL certificate on this status.
+	void setErrorData(void *data)
+	{
+		mDetails->mErrorData = data;
+	}
+
+private:
+
+	struct Details
+	{
+		Details(type_enum_t type, short status):
+			mType(type),
+			mStatus(status),
+			mMessage(),
+			mErrorData(NULL)
+		{}
+
+		Details(const Details &rhs) :
+			mType(rhs.mType),
+			mStatus(rhs.mStatus),
+			mMessage(rhs.mMessage),
+			mErrorData(rhs.mErrorData)
+		{}
+
+        bool operator == (const Details &rhs) const
+        {
+            return (mType == rhs.mType) && (mStatus == rhs.mStatus);
+        }
+
+		type_enum_t	mType;
+		short		mStatus;
+		std::string	mMessage;
+		void *		mErrorData;
+	};
+
+    boost::shared_ptr<Details> mDetails;
+
 }; // end struct HttpStatus
 
+///  A namespace for several free methods and low level utilities. 
+namespace LLHttp
+{
+    typedef boost::shared_ptr<CURL> CURL_ptr;
+
+    void initialize();
+    void cleanup();
+
+    CURL_ptr createEasyHandle();
+    std::string getCURLVersion();
+
+    void check_curl_code(CURLcode code, int curl_setopt_option);
+}
+
 }  // end namespace LLCore
 
 #endif	// _LLCORE_HTTP_COMMON_H_
diff --git a/indra/llcorehttp/httphandler.h b/indra/llcorehttp/httphandler.h
index 9171e4e7b930252a6bb0e9e8d62adaa085c9d5f5..7bc9096703029aa0999a54659bab6d2f325b1e18 100755
--- a/indra/llcorehttp/httphandler.h
+++ b/indra/llcorehttp/httphandler.h
@@ -45,7 +45,7 @@ class HttpResponse;
 /// be shared by any number of requests and across instances
 /// of HttpRequest running in the same thread.
 ///
-/// Threading:  HttpHandler itself is pure interface and is
+/// Threading:  HttpHandler itself is interface and is
 /// tread-compatible.  Most derivations, however, will have
 /// different constraints.
 ///
@@ -53,12 +53,13 @@ class HttpResponse;
 /// that is rarely a good idea.  Queued requests and replies keep
 /// a naked pointer to the handler and this can result in a
 /// dangling pointer if lifetimes aren't managed correctly.
-
-class HttpHandler
+///
+/// *TODO: public std::enable_shared_from_this<HttpHandler>
+class HttpHandler 
 {
 public:
 	virtual ~HttpHandler()
-		{}
+	{ }
 
 	/// Method invoked during calls to @see update().  Each invocation
 	/// represents the completion of some requested operation.  Caller
diff --git a/indra/llcorehttp/httpheaders.cpp b/indra/llcorehttp/httpheaders.cpp
index 23ebea361c1246b7589918cab569e2527be70d5e..f586191a7c5af105e21d955667c1fec09d23cb51 100755
--- a/indra/llcorehttp/httpheaders.cpp
+++ b/indra/llcorehttp/httpheaders.cpp
@@ -34,7 +34,6 @@ namespace LLCore
 
 
 HttpHeaders::HttpHeaders()
-	: RefCounted(true)
 {}
 
 
@@ -105,7 +104,7 @@ void HttpHeaders::appendNormal(const char * header, size_t size)
 
 // Find from end to simulate a tradition of using single-valued
 // std::map for this in the past.
-const std::string * HttpHeaders::find(const char * name) const
+const std::string * HttpHeaders::find(const std::string &name) const
 {
 	const_reverse_iterator iend(rend());
 	for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)
@@ -118,6 +117,24 @@ const std::string * HttpHeaders::find(const char * name) const
 	return NULL;
 }
 
+void HttpHeaders::remove(const char *name)
+{
+    remove(std::string(name));
+}
+
+void HttpHeaders::remove(const std::string &name)
+{
+    iterator iend(end());
+    for (iterator iter(begin()); iend != iter; ++iter)
+    {
+        if ((*iter).first == name)
+        {
+            mHeaders.erase(iter);
+            return;
+        }
+    }
+}
+
 
 // Standard Iterators
 HttpHeaders::iterator HttpHeaders::begin()
diff --git a/indra/llcorehttp/httpheaders.h b/indra/llcorehttp/httpheaders.h
index f70cd898f3949eb641991bd76fdd3650c5abe885..b9168cb6ec86eff22e4e68eae33460cef2d4f8c9 100755
--- a/indra/llcorehttp/httpheaders.h
+++ b/indra/llcorehttp/httpheaders.h
@@ -28,8 +28,8 @@
 #define	_LLCORE_HTTP_HEADERS_H_
 
 
+#include "httpcommon.h"
 #include <string>
-
 #include "_refcounted.h"
 
 
@@ -74,7 +74,7 @@ namespace LLCore
 /// constructor is given a refcount.
 ///
 
-class HttpHeaders : public LLCoreInt::RefCounted
+class HttpHeaders: private boost::noncopyable
 {
 public:
 	typedef std::pair<std::string, std::string> header_t;
@@ -85,15 +85,17 @@ class HttpHeaders : public LLCoreInt::RefCounted
 	typedef container_t::const_reverse_iterator const_reverse_iterator;
 	typedef container_t::value_type value_type;
 	typedef container_t::size_type size_type;
+    typedef boost::shared_ptr<HttpHeaders> ptr_t;
 
 public:
 	/// @post In addition to the instance, caller has a refcount
 	/// to the instance.  A call to @see release() will destroy
 	/// the instance.
 	HttpHeaders();
+    virtual ~HttpHeaders();						// Use release()
 
+	//typedef LLCoreInt::IntrusivePtr<HttpHeaders> ptr_t;
 protected:
-	virtual ~HttpHeaders();						// Use release()
 
 	HttpHeaders(const HttpHeaders &);			// Not defined
 	void operator=(const HttpHeaders &);		// Not defined
@@ -145,8 +147,16 @@ class HttpHeaders : public LLCoreInt::RefCounted
 	//					a pointer to a std::string in the container.
 	//					Pointer is valid only for the lifetime of
 	//					the container or until container is modifed.
-	//
-	const std::string * find(const char * name) const;
+	const std::string * find(const std::string &name) const;
+	const std::string * find(const char * name) const
+	{
+		return find(std::string(name));
+	}
+
+    // Remove the header from the list if found.
+    // 
+    void remove(const std::string &name);
+    void remove(const char *name);
 
 	// Count of headers currently in the list.
 	size_type size() const
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index 5bf1ecb4a5a98376a47c5f6b50a2aad68a3412a3..aab447f2dd11f5bc3fb1e35c33d19b4db0d36da5 100755
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -25,7 +25,7 @@
  */
 
 #include "httpoptions.h"
-
+#include "lldefs.h"
 #include "_httpinternal.h"
 
 
@@ -33,14 +33,18 @@ namespace LLCore
 {
 
 
-HttpOptions::HttpOptions()
-	: RefCounted(true),
-	  mWantHeaders(false),
-	  mTracing(HTTP_TRACE_OFF),
-	  mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
-	  mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
-	  mRetries(HTTP_RETRY_COUNT_DEFAULT),
-	  mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT)
+HttpOptions::HttpOptions() :
+    mWantHeaders(false),
+    mTracing(HTTP_TRACE_OFF),
+    mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
+    mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
+    mRetries(HTTP_RETRY_COUNT_DEFAULT),
+    mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),
+    mFollowRedirects(true),
+    mVerifyPeer(false),
+    mVerifyHost(false),
+    mDNSCacheTimeout(-1L),
+    mNoBody(false)
 {}
 
 
@@ -82,5 +86,31 @@ void HttpOptions::setUseRetryAfter(bool use_retry)
 	mUseRetryAfter = use_retry;
 }
 
+void HttpOptions::setFollowRedirects(bool follow_redirect)
+{
+	mFollowRedirects = follow_redirect;
+}
+
+void HttpOptions::setSSLVerifyPeer(bool verify)
+{
+	mVerifyPeer = verify;
+}
+
+void HttpOptions::setSSLVerifyHost(bool verify)
+{
+	mVerifyHost = verify;
+}
+
+void HttpOptions::setDNSCacheTimeout(int timeout)
+{
+	mDNSCacheTimeout = timeout;
+}
+
+void HttpOptions::setHeadersOnly(bool nobody)
+{
+    mNoBody = nobody;
+    if (mNoBody)
+        setWantHeaders(true);
+}
 
 }   // end namespace LLCore
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 4ab5ff18c43ba29ec1b68dde1b1406989ae14818..510eaa45bba158e08a0b9f4bdf3cc04d42eadc77 100755
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -29,7 +29,6 @@
 
 
 #include "httpcommon.h"
-
 #include "_refcounted.h"
 
 
@@ -56,59 +55,110 @@ namespace LLCore
 /// Allocation:  Refcounted, heap only.  Caller of the constructor
 /// is given a refcount.
 ///
-class HttpOptions : public LLCoreInt::RefCounted
+class HttpOptions : private boost::noncopyable
 {
 public:
 	HttpOptions();
 
+	typedef boost::shared_ptr<HttpOptions> ptr_t;
+
+    virtual ~HttpOptions();						// Use release()
+
 protected:
-	virtual ~HttpOptions();						// Use release()
 	
 	HttpOptions(const HttpOptions &);			// Not defined
 	void operator=(const HttpOptions &);		// Not defined
 
 public:
+
 	// Default:   false
 	void				setWantHeaders(bool wanted);
 	bool				getWantHeaders() const
-		{
-			return mWantHeaders;
-		}
+	{
+		return mWantHeaders;
+	}
 
 	// Default:  0
 	void				setTrace(int long);
 	int					getTrace() const
-		{
-			return mTracing;
-		}
+	{
+		return mTracing;
+	}
 
 	// Default:  30
 	void				setTimeout(unsigned int timeout);
 	unsigned int		getTimeout() const
-		{
-			return mTimeout;
-		}
+	{
+		return mTimeout;
+	}
 
 	// Default:  0
 	void				setTransferTimeout(unsigned int timeout);
 	unsigned int		getTransferTimeout() const
-		{
-			return mTransferTimeout;
-		}
+	{
+		return mTransferTimeout;
+	}
 
+    /// Sets the number of retries on an LLCore::HTTPRequest before the 
+    /// request fails.
 	// Default:  8
 	void				setRetries(unsigned int retries);
 	unsigned int		getRetries() const
-		{
-			return mRetries;
-		}
+	{
+		return mRetries;
+	}
 
 	// Default:  true
 	void				setUseRetryAfter(bool use_retry);
 	bool				getUseRetryAfter() const
-		{
-			return mUseRetryAfter;
-		}
+	{
+		return mUseRetryAfter;
+	}
+
+    /// Instructs the LLCore::HTTPRequest to follow redirects 
+	/// Default: false
+	void				setFollowRedirects(bool follow_redirect);
+	bool				getFollowRedirects() const
+	{
+		return mFollowRedirects;
+	}
+
+    /// Instructs the LLCore::HTTPRequest to verify that the exchanged security
+    /// certificate is authentic. 
+    /// Default: false
+    void				setSSLVerifyPeer(bool verify);
+	bool				getSSLVerifyPeer() const
+	{
+		return mVerifyPeer;
+	}
+
+    /// Instructs the LLCore::HTTPRequest to verify that the name in the 
+    /// security certificate matches the name of the host contacted.
+    /// Default: false
+    void				setSSLVerifyHost(bool verify);
+	bool	        	getSSLVerifyHost() const
+	{
+		return mVerifyHost;
+	}
+
+    /// Sets the time for DNS name caching in seconds.  Setting this value
+    /// to 0 will disable name caching.  Setting this value to -1 causes the 
+    /// name cache to never time out.
+    /// Default: -1
+	void				setDNSCacheTimeout(int timeout);
+	int					getDNSCacheTimeout() const
+	{
+		return mDNSCacheTimeout;
+	}
+
+    /// Retrieve only the headers and status from the request. Setting this 
+    /// to true implies setWantHeaders(true) as well.
+    /// Default: false
+    void                setHeadersOnly(bool nobody);
+    bool                getHeadersOnly() const
+    {
+        return mNoBody;
+    }
 	
 protected:
 	bool				mWantHeaders;
@@ -117,6 +167,11 @@ class HttpOptions : public LLCoreInt::RefCounted
 	unsigned int		mTransferTimeout;
 	unsigned int		mRetries;
 	bool				mUseRetryAfter;
+	bool				mFollowRedirects;
+	bool				mVerifyPeer;
+	bool        		mVerifyHost;
+	int					mDNSCacheTimeout;
+    bool                mNoBody;
 }; // end class HttpOptions
 
 
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 7b1888e3ebad9a16bed8511498c6d83ecf24367c..63233259fb9885a9a69edaec1ac330d9af38825d 100755
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -117,6 +117,15 @@ HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass
 	return HttpService::instanceOf()->setPolicyOption(opt, pclass, value, ret_value);
 }
 
+HttpStatus HttpRequest::setStaticPolicyOption(EPolicyOption opt, policy_t pclass, policyCallback_t value, policyCallback_t * ret_value)
+{
+	if (HttpService::RUNNING == HttpService::instanceOf()->getState())
+	{
+		return HttpStatus(HttpStatus::LLCORE, HE_OPT_NOT_DYNAMIC);
+	}
+
+	return HttpService::instanceOf()->setPolicyOption(opt, pclass, value, ret_value);
+}
 
 HttpHandle HttpRequest::setPolicyOption(EPolicyOption opt, policy_t pclass,
 										long value, HttpHandler * handler)
@@ -188,8 +197,8 @@ HttpStatus HttpRequest::getStatus() const
 HttpHandle HttpRequest::requestGet(policy_t policy_id,
 								   priority_t priority,
 								   const std::string & url,
-								   HttpOptions * options,
-								   HttpHeaders * headers,
+                                   const HttpOptions::ptr_t & options,
+								   const HttpHeaders::ptr_t & headers,
 								   HttpHandler * user_handler)
 {
 	HttpStatus status;
@@ -222,8 +231,8 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
 											const std::string & url,
 											size_t offset,
 											size_t len,
-											HttpOptions * options,
-											HttpHeaders * headers,
+                                            const HttpOptions::ptr_t & options,
+											const HttpHeaders::ptr_t & headers,
 											HttpHandler * user_handler)
 {
 	HttpStatus status;
@@ -255,8 +264,8 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
 									priority_t priority,
 									const std::string & url,
 									BufferArray * body,
-									HttpOptions * options,
-									HttpHeaders * headers,
+                                    const HttpOptions::ptr_t & options,
+									const HttpHeaders::ptr_t & headers,
 									HttpHandler * user_handler)
 {
 	HttpStatus status;
@@ -288,8 +297,8 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
 								   priority_t priority,
 								   const std::string & url,
 								   BufferArray * body,
-								   HttpOptions * options,
-								   HttpHeaders * headers,
+                                   const HttpOptions::ptr_t & options,
+								   const HttpHeaders::ptr_t & headers,
 								   HttpHandler * user_handler)
 {
 	HttpStatus status;
@@ -316,6 +325,131 @@ HttpHandle HttpRequest::requestPut(policy_t policy_id,
 	return handle;
 }
 
+HttpHandle HttpRequest::requestDelete(policy_t policy_id,
+    priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers,
+    HttpHandler * user_handler)
+{
+    HttpStatus status;
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    HttpOpRequest * op = new HttpOpRequest();
+    if (!(status = op->setupDelete(policy_id, priority, url, options, headers)))
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+    op->setReplyPath(mReplyQueue, user_handler);
+    if (!(status = mRequestQueue->addOp(op)))			// transfers refcount
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+
+    mLastReqStatus = status;
+    handle = static_cast<HttpHandle>(op);
+
+    return handle;
+}
+
+HttpHandle HttpRequest::requestPatch(policy_t policy_id,
+    priority_t priority,
+    const std::string & url,
+    BufferArray * body,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers,
+    HttpHandler * user_handler)
+{
+    HttpStatus status;
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    HttpOpRequest * op = new HttpOpRequest();
+    if (!(status = op->setupPatch(policy_id, priority, url, body, options, headers)))
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+    op->setReplyPath(mReplyQueue, user_handler);
+    if (!(status = mRequestQueue->addOp(op)))			// transfers refcount
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+
+    mLastReqStatus = status;
+    handle = static_cast<HttpHandle>(op);
+
+    return handle;
+}
+
+HttpHandle HttpRequest::requestCopy(policy_t policy_id,
+    priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers,
+    HttpHandler * user_handler)
+{
+    HttpStatus status;
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    HttpOpRequest * op = new HttpOpRequest();
+    if (!(status = op->setupCopy(policy_id, priority, url, options, headers)))
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+    op->setReplyPath(mReplyQueue, user_handler);
+    if (!(status = mRequestQueue->addOp(op)))			// transfers refcount
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+
+    mLastReqStatus = status;
+    handle = static_cast<HttpHandle>(op);
+
+    return handle;
+}
+
+HttpHandle HttpRequest::requestMove(policy_t policy_id,
+    priority_t priority,
+    const std::string & url,
+    const HttpOptions::ptr_t & options,
+    const HttpHeaders::ptr_t & headers,
+    HttpHandler * user_handler)
+{
+    HttpStatus status;
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    HttpOpRequest * op = new HttpOpRequest();
+    if (!(status = op->setupMove(policy_id, priority, url, options, headers)))
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+    op->setReplyPath(mReplyQueue, user_handler);
+    if (!(status = mRequestQueue->addOp(op)))			// transfers refcount
+    {
+        op->release();
+        mLastReqStatus = status;
+        return handle;
+    }
+
+    mLastReqStatus = status;
+    handle = static_cast<HttpHandle>(op);
+
+    return handle;
+}
+
 
 HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)
 {
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 7f23723b0b005a5f44a4380594d49f605a444423..6c2449266f5694892d90494b1e7460b5ba17a9e7 100755
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -31,6 +31,8 @@
 #include "httpcommon.h"
 #include "httphandler.h"
 
+#include "httpheaders.h"
+#include "httpoptions.h"
 
 namespace LLCore
 {
@@ -38,8 +40,6 @@ namespace LLCore
 class HttpRequestQueue;
 class HttpReplyQueue;
 class HttpService;
-class HttpOptions;
-class HttpHeaders;
 class HttpOperation;
 class BufferArray;
 
@@ -97,6 +97,8 @@ class HttpRequest
 	typedef unsigned int policy_t;
 	typedef unsigned int priority_t;
 	
+	typedef boost::shared_ptr<HttpRequest> ptr_t;
+    typedef boost::weak_ptr<HttpRequest>   wptr_t;
 public:
 	/// @name PolicyMethods
 	/// @{
@@ -163,7 +165,7 @@ class HttpRequest
 
 		/// Long value that if non-zero enables the use of the
 		/// traditional LLProxy code for http/socks5 support.  If
-		// enabled, has priority over GP_HTTP_PROXY.
+		/// enabled, has priority over GP_HTTP_PROXY.
 		///
 		/// Global only
 		PO_LLPROXY,
@@ -219,15 +221,25 @@ class HttpRequest
 		/// Controls whether client-side throttling should be
 		/// performed on this policy class.  Positive values
 		/// enable throttling and specify the request rate
-		/// (requests per second) that should be targetted.
+		/// (requests per second) that should be targeted.
 		/// A value of zero, the default, specifies no throttling.
 		///
 		/// Per-class only
 		PO_THROTTLE_RATE,
 		
+		/// Controls the callback function used to control SSL CTX 
+		/// certificate verification.
+		///
+		/// Global only
+		PO_SSL_VERIFY_CALLBACK,
+
 		PO_LAST  // Always at end
 	};
 
+	/// Prototype for policy based callbacks.  The callback methods will be executed
+	/// on the worker thread so no modifications should be made to the HttpHandler object.
+    typedef boost::function<HttpStatus(const std::string &, HttpHandler const * const, void *)> policyCallback_t;
+
 	/// Set a policy option for a global or class parameter at
 	/// startup time (prior to thread start).
 	///
@@ -243,6 +255,8 @@ class HttpRequest
 											long value, long * ret_value);
 	static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass,
 											const std::string & value, std::string * ret_value);
+	static HttpStatus setStaticPolicyOption(EPolicyOption opt, policy_t pclass,
+											policyCallback_t value, policyCallback_t * ret_value);;
 
 	/// Set a parameter on a class-based policy option.  Calls
 	/// made after the start of the servicing thread are
@@ -334,8 +348,8 @@ class HttpRequest
 	HttpHandle requestGet(policy_t policy_id,
 						  priority_t priority,
 						  const std::string & url,
-						  HttpOptions * options,
-						  HttpHeaders * headers,
+                          const HttpOptions::ptr_t & options,
+						  const HttpHeaders::ptr_t & headers,
 						  HttpHandler * handler);
 
 
@@ -377,8 +391,8 @@ class HttpRequest
 								   const std::string & url,
 								   size_t offset,
 								   size_t len,
-								   HttpOptions * options,
-								   HttpHeaders * headers,
+                                   const HttpOptions::ptr_t & options,
+								   const HttpHeaders::ptr_t & headers,
 								   HttpHandler * handler);
 
 
@@ -418,8 +432,8 @@ class HttpRequest
 						   priority_t priority,
 						   const std::string & url,
 						   BufferArray * body,
-						   HttpOptions * options,
-						   HttpHeaders * headers,
+                           const HttpOptions::ptr_t & options,
+						   const HttpHeaders::ptr_t & headers,
 						   HttpHandler * handler);
 
 
@@ -459,12 +473,92 @@ class HttpRequest
 						  priority_t priority,
 						  const std::string & url,
 						  BufferArray * body,
-						  HttpOptions * options,
-						  HttpHeaders * headers,
+                          const HttpOptions::ptr_t & options,
+						  const HttpHeaders::ptr_t & headers,
 						  HttpHandler * handler);
 
 
-	/// Queue a NoOp request.
+    /// Queue a full HTTP DELETE.  Query arguments and body may
+    /// be provided.  Caller is responsible for escaping and
+    /// encoding and communicating the content types.
+    ///
+    /// @param	policy_id		@see requestGet()
+    /// @param	priority		"
+    /// @param	url				"
+    /// @param	options			@see requestGet()K(optional)
+    /// @param	headers			"
+    /// @param	handler			"
+    /// @return					"
+    ///
+    HttpHandle requestDelete(policy_t policy_id,
+            priority_t priority,
+            const std::string & url,
+            const HttpOptions::ptr_t & options,
+            const HttpHeaders::ptr_t & headers,
+            HttpHandler * user_handler);
+
+    /// Queue a full HTTP PATCH.  Query arguments and body may
+    /// be provided.  Caller is responsible for escaping and
+    /// encoding and communicating the content types.
+    ///
+    /// @param	policy_id		@see requestGet()
+    /// @param	priority		"
+    /// @param	url				"
+    /// @param	body			Byte stream to be sent as the body.  No
+    ///							further encoding or escaping will be done
+    ///							to the content.
+    /// @param	options			@see requestGet()K(optional)
+    /// @param	headers			"
+    /// @param	handler			"
+    /// @return					"
+    ///
+    HttpHandle requestPatch(policy_t policy_id,
+            priority_t priority,
+            const std::string & url,
+            BufferArray * body,
+            const HttpOptions::ptr_t & options,
+            const HttpHeaders::ptr_t & headers,
+            HttpHandler * user_handler);
+
+    /// Queue a full HTTP COPY.  Query arguments and body may
+    /// be provided.  Caller is responsible for escaping and
+    /// encoding and communicating the content types.
+    ///
+    /// @param	policy_id		@see requestGet()
+    /// @param	priority		"
+    /// @param	url				"
+    /// @param	options			@see requestGet()K(optional)
+    /// @param	headers			"
+    /// @param	handler			"
+    /// @return					"
+    ///
+    HttpHandle requestCopy(policy_t policy_id,
+            priority_t priority,
+            const std::string & url,
+            const HttpOptions::ptr_t & options,
+            const HttpHeaders::ptr_t & headers,
+            HttpHandler * user_handler);
+
+    /// Queue a full HTTP MOVE.  Query arguments and body may
+    /// be provided.  Caller is responsible for escaping and
+    /// encoding and communicating the content types.
+    ///
+    /// @param	policy_id		@see requestGet()
+    /// @param	priority		"
+    /// @param	url				"
+    /// @param	options			@see requestGet()K(optional)
+    /// @param	headers			"
+    /// @param	handler			"
+    /// @return					"
+    ///
+    HttpHandle requestMove(policy_t policy_id,
+            priority_t priority,
+            const std::string & url,
+            const HttpOptions::ptr_t & options,
+            const HttpHeaders::ptr_t & headers,
+            HttpHandler * user_handler);
+
+    /// Queue a NoOp request.
 	/// The request is queued and serviced by the working thread which
 	/// immediately processes it and returns the request to the reply
 	/// queue.
diff --git a/indra/llcorehttp/httpresponse.cpp b/indra/llcorehttp/httpresponse.cpp
index c974395b0a53c60bc334d7cb91d3da9dd032c546..f5ad2ebd47295c5b4adb09282db293355ce93ca1 100755
--- a/indra/llcorehttp/httpresponse.cpp
+++ b/indra/llcorehttp/httpresponse.cpp
@@ -39,16 +39,17 @@ HttpResponse::HttpResponse()
 	  mReplyLength(0U),
 	  mReplyFullLength(0U),
 	  mBufferArray(NULL),
-	  mHeaders(NULL),
+	  mHeaders(),
 	  mRetries(0U),
-	  m503Retries(0U)
+	  m503Retries(0U),
+      mRequestUrl()
 {}
 
 
 HttpResponse::~HttpResponse()
 {
 	setBody(NULL);
-	setHeaders(NULL);
+	//setHeaders();
 }
 
 
@@ -71,23 +72,14 @@ void HttpResponse::setBody(BufferArray * ba)
 }
 
 
-void HttpResponse::setHeaders(HttpHeaders * headers)
+void HttpResponse::setHeaders(HttpHeaders::ptr_t &headers)
 {
-	if (mHeaders == headers)
-		return;
-	
-	if (mHeaders)
-	{
-		mHeaders->release();
-	}
-
-	if (headers)
-	{
-		headers->addRef();
-	}
-	
-	mHeaders = headers;
+    mHeaders = headers;
 }
 
+size_t HttpResponse::getBodySize() const
+{
+	return (mBufferArray) ? mBufferArray->size() : 0;
+}
 
 }   // end namespace LLCore
diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h
index aee64e28784b99c63342abed863ea11f2f588b75..0bfa4585c70a134684685fb5eeb88f4a4d701de0 100755
--- a/indra/llcorehttp/httpresponse.h
+++ b/indra/llcorehttp/httpresponse.h
@@ -31,7 +31,7 @@
 #include <string>
 
 #include "httpcommon.h"
-
+#include "httpheaders.h"
 #include "_refcounted.h"
 
 
@@ -69,6 +69,18 @@ class HttpResponse : public LLCoreInt::RefCounted
 	void operator=(const HttpResponse &);				// Not defined
 	
 public:
+	/// Statistics for the HTTP 
+	struct TransferStats
+	{
+		typedef boost::shared_ptr<TransferStats> ptr_t;
+
+		TransferStats() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
+		F64 mSizeDownload;
+		F64 mTotalTime;
+		F64 mSpeedDownload;
+	};
+
+
 	/// Returns the final status of the requested operation.
 	///
 	HttpStatus getStatus() const
@@ -92,6 +104,10 @@ class HttpResponse : public LLCoreInt::RefCounted
 			return mBufferArray;
 		}
 
+	/// Safely get the size of the body buffer.  If the body buffer is missing
+	/// return 0 as the size.
+	size_t getBodySize() const;
+
 	/// Set the response data in the instance.  Will drop the reference
 	/// count to any existing data and increment the count of that passed
 	/// in.  It is legal to set the data to NULL.
@@ -104,13 +120,13 @@ class HttpResponse : public LLCoreInt::RefCounted
 	///
 	/// Caller can hold onto the headers by incrementing the reference
 	/// count of the returned object.
-	HttpHeaders * getHeaders() const
-		{
+	HttpHeaders::ptr_t getHeaders() const
+	{
 			return mHeaders;
-		}
+	}
 
 	/// Behaves like @see setResponse() but for header data.
-	void setHeaders(HttpHeaders * headers);
+	void setHeaders(HttpHeaders::ptr_t &headers);
 
 	/// If a 'Range:' header was used, these methods are involved
 	/// in setting and returning data about the actual response.
@@ -168,6 +184,27 @@ class HttpResponse : public LLCoreInt::RefCounted
 			m503Retries = retries_503;
 		}
 
+	void setTransferStats(TransferStats::ptr_t &stats) 
+		{
+			mStats = stats;
+		}
+
+	TransferStats::ptr_t getTransferStats()
+		{
+			return mStats;
+		}
+
+    void setRequestURL(const std::string &url)
+        {
+            mRequestUrl = url;
+        }
+
+    const std::string &getRequestURL() const
+        {
+            return mRequestUrl;
+        }
+
+
 protected:
 	// Response data here
 	HttpStatus			mStatus;
@@ -175,10 +212,13 @@ class HttpResponse : public LLCoreInt::RefCounted
 	unsigned int		mReplyLength;
 	unsigned int		mReplyFullLength;
 	BufferArray *		mBufferArray;
-	HttpHeaders *		mHeaders;
+	HttpHeaders::ptr_t	mHeaders;
 	std::string			mContentType;
 	unsigned int		mRetries;
 	unsigned int		m503Retries;
+    std::string         mRequestUrl;
+
+	TransferStats::ptr_t	mStats;
 };
 
 
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llcorehttp/llhttpconstants.cpp
similarity index 75%
rename from indra/llmessage/llhttpconstants.cpp
rename to indra/llcorehttp/llhttpconstants.cpp
index 32f76f0d7004601a18bd4c4f3638401ac502a413..71d4f19408de893f74be515b89ec75950fa334eb 100755
--- a/indra/llmessage/llhttpconstants.cpp
+++ b/indra/llcorehttp/llhttpconstants.cpp
@@ -133,94 +133,3 @@ const std::string HTTP_VERB_MOVE("MOVE");
 const std::string HTTP_VERB_OPTIONS("OPTIONS");
 const std::string HTTP_VERB_PATCH("PATCH");
 const std::string HTTP_VERB_COPY("COPY");
-
-const std::string& httpMethodAsVerb(EHTTPMethod method)
-{
-	static const std::string VERBS[] =
-	{
-		HTTP_VERB_INVALID,
-		HTTP_VERB_HEAD,
-		HTTP_VERB_GET,
-		HTTP_VERB_PUT,
-		HTTP_VERB_POST,
-		HTTP_VERB_DELETE,
-		HTTP_VERB_MOVE,
-		HTTP_VERB_OPTIONS,
-		HTTP_VERB_PATCH,
-		HTTP_VERB_COPY
-	};
-	if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT))
-	{
-		return VERBS[0];
-	}
-	return VERBS[method];
-}
-
-bool isHttpInformationalStatus(S32 status)
-{
-	// Check for status 1xx.
-	return((100 <= status) && (status < 200));
-}
-
-bool isHttpGoodStatus(S32 status)
-{
-	// Check for status 2xx.
-	return((200 <= status) && (status < 300));
-}
-
-bool isHttpRedirectStatus(S32 status)
-{
-	// Check for status 3xx.
-	return((300 <= status) && (status < 400));
-}
-
-bool isHttpClientErrorStatus(S32 status)
-{
-	// Status 499 is sometimes used for re-interpreted status 2xx errors
-	// based on body content.  Treat these as potentially retryable 'server' status errors,
-	// since we do not have enough context to know if this will always fail.
-	if (HTTP_INTERNAL_ERROR == status) return false;
-
-	// Check for status 5xx.
-	return((400 <= status) && (status < 500));
-}
-
-bool isHttpServerErrorStatus(S32 status)
-{
-	// Status 499 is sometimes used for re-interpreted status 2xx errors.
-	// Allow retry of these, since we don't have enough information in this
-	// context to know if this will always fail.
-	if (HTTP_INTERNAL_ERROR == status) return true;
-
-	// Check for status 5xx.
-	return((500 <= status) && (status < 600));
-}
-
-// Parses 'Retry-After' header contents and returns seconds until retry should occur.
-bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
-{
-	// *TODO:  This needs testing!   Not in use yet.
-	// Examples of Retry-After headers:
-	// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
-	// Retry-After: 120
-
-	// Check for number of seconds version, first:
-	char* end = 0;
-	// Parse as double
-	double seconds = std::strtod(retry_after.c_str(), &end);
-	if ( end != 0 && *end == 0 )
-	{
-		// Successful parse
-		seconds_to_wait = (F32) seconds;
-		return true;
-	}
-
-	// Parse rfc1123 date.
-	time_t date = curl_getdate(retry_after.c_str(), NULL );
-	if (-1 == date) return false;
-
-	seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
-
-	return true;
-}
-
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llcorehttp/llhttpconstants.h
similarity index 97%
rename from indra/llmessage/llhttpconstants.h
rename to indra/llcorehttp/llhttpconstants.h
index d6bcbd3c19329ed1a2aa1bd4bcfdd1ed4bbde317..121448854eb622a880c512dbd39566b9ace19906 100755
--- a/indra/llmessage/llhttpconstants.h
+++ b/indra/llcorehttp/llhttpconstants.h
@@ -116,13 +116,6 @@ enum EHTTPMethod
 	HTTP_METHOD_COUNT
 };
 
-const std::string& httpMethodAsVerb(EHTTPMethod method);
-bool isHttpInformationalStatus(S32 status);
-bool isHttpGoodStatus(S32 status);
-bool isHttpRedirectStatus(S32 status);
-bool isHttpClientErrorStatus(S32 status);
-bool isHttpServerErrorStatus(S32 status);
-
 // Parses 'Retry-After' header contents and returns seconds until retry should occur.
 bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
 
diff --git a/indra/llcorehttp/tests/test_httpheaders.hpp b/indra/llcorehttp/tests/test_httpheaders.hpp
index 668c36dc66bc142947a99546dee4ee6e152be5be..c05f1d9429ceddb82c2d2870e4129d21dc2c2cc8 100755
--- a/indra/llcorehttp/tests/test_httpheaders.hpp
+++ b/indra/llcorehttp/tests/test_httpheaders.hpp
@@ -59,13 +59,12 @@ void HttpHeadersTestObjectType::test<1>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
-	ensure("One ref on construction of HttpHeaders", headers->getRefCount() == 1);
+	HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
 	ensure("Memory being used", mMemTotal < GetMemTotal());
 	ensure("Nothing in headers", 0 == headers->size());
 
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
@@ -80,7 +79,7 @@ void HttpHeadersTestObjectType::test<2>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
+	HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
 	
 	{
 		// Append a few strings
@@ -101,7 +100,7 @@ void HttpHeadersTestObjectType::test<2>()
 	}
 	
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
@@ -116,7 +115,7 @@ void HttpHeadersTestObjectType::test<3>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
+	HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
 	
 	{
 		// Append a few strings
@@ -151,7 +150,7 @@ void HttpHeadersTestObjectType::test<3>()
 	}
 	
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
@@ -166,8 +165,8 @@ void HttpHeadersTestObjectType::test<4>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
-	
+    HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
+
 	{
 		static char line1[] = " AcCePT : image/yourfacehere";
 		static char line1v[] = "image/yourfacehere";
@@ -251,7 +250,7 @@ void HttpHeadersTestObjectType::test<4>()
 	}
 	
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
@@ -267,7 +266,7 @@ void HttpHeadersTestObjectType::test<5>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
+    HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
 
 	HttpHeaders::iterator end(headers->end()), begin(headers->begin());
 	ensure("Empty container has equal begin/end const iterators", end == begin);
@@ -337,7 +336,7 @@ void HttpHeadersTestObjectType::test<5>()
 	}
 	
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
@@ -353,7 +352,7 @@ void HttpHeadersTestObjectType::test<6>()
 	mMemTotal = GetMemTotal();
 
 	// create a new ref counted object with an implicit reference
-	HttpHeaders * headers = new HttpHeaders();
+    HttpHeaders::ptr_t headers = HttpHeaders::ptr_t(new HttpHeaders());
 
 	HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
 	ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
@@ -421,7 +420,7 @@ void HttpHeadersTestObjectType::test<6>()
 	}
 	
 	// release the implicit reference, causing the object to be released
-	headers->release();
+    headers.reset();
 
 	// make sure we didn't leak any memory
 	ensure(mMemTotal == GetMemTotal());
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 43f7e36da5398d73337c724622d69d568cb997c1..1f606bd0c198f0e0be881d0d081f3b0c4be2b329 100755
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -112,7 +112,7 @@ public:
 			if (! mHeadersRequired.empty() || ! mHeadersDisallowed.empty())
 			{
 				ensure("Response required with header check", response != NULL);
-				HttpHeaders * header(response->getHeaders());	// Will not hold onto this
+				HttpHeaders::ptr_t header(response->getHeaders());	// Will not hold onto this
 				ensure("Some quantity of headers returned", header != NULL);
 
 				if (! mHeadersRequired.empty())
@@ -638,7 +638,7 @@ void HttpRequestTestObjectType::test<7>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * opts = NULL;
+	HttpOptions::ptr_t opts;
 	
 	try
 	{
@@ -653,7 +653,7 @@ void HttpRequestTestObjectType::test<7>()
 		req = new HttpRequest();
 		ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
 
-		opts = new HttpOptions();
+        opts = HttpOptions::ptr_t(new HttpOptions());
 		opts->setRetries(1);			// Don't try for too long - default retries take about 18S
 		
 		// Issue a GET that can't connect
@@ -664,7 +664,7 @@ void HttpRequestTestObjectType::test<7>()
 													 0,
 													 0,
 													 opts,
-													 NULL,
+													 HttpHeaders::ptr_t(),
 													 &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
@@ -705,8 +705,7 @@ void HttpRequestTestObjectType::test<7>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 
 		// release options
-		opts->release();
-		opts = NULL;
+        opts.reset();
 		
 		// release the request object
 		delete req;
@@ -728,11 +727,7 @@ void HttpRequestTestObjectType::test<7>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (opts)
-		{
-			opts->release();
-			opts = NULL;
-		}
+        opts.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -779,8 +774,8 @@ void HttpRequestTestObjectType::test<8>()
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base,
-											NULL,
-											NULL,
+											HttpOptions::ptr_t(),
+                                            HttpHeaders::ptr_t(),
 											&handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
@@ -889,8 +884,8 @@ void HttpRequestTestObjectType::test<9>()
 													 url_base,
 													 0,
 													 0,
-													 NULL,
-													 NULL,
+													 HttpOptions::ptr_t(),
+                                                     HttpHeaders::ptr_t(),
 													 &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
@@ -1001,9 +996,9 @@ void HttpRequestTestObjectType::test<10>()
 											0U,
 											url_base,
 											body,
-											NULL,
-											NULL,
-											&handler);
+                                            HttpOptions::ptr_t(),
+                                            HttpHeaders::ptr_t(),
+                                            &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// Run the notification pump.
@@ -1119,9 +1114,9 @@ void HttpRequestTestObjectType::test<11>()
 											 0U,
 											 url_base,
 											 body,
-											 NULL,
-											 NULL,
-											 &handler);
+                                             HttpOptions::ptr_t(),
+                                             HttpHeaders::ptr_t(),
+                                             &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// Run the notification pump.
@@ -1239,9 +1234,9 @@ void HttpRequestTestObjectType::test<12>()
 													 url_base,
 													 0,
 													 0,
-													 NULL,
-													 NULL,
-													 &handler);
+                                                     HttpOptions::ptr_t(),
+                                                     HttpHeaders::ptr_t(),
+                                                     &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// Run the notification pump.
@@ -1332,7 +1327,7 @@ void HttpRequestTestObjectType::test<13>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * opts = NULL;
+	HttpOptions::ptr_t opts;
 
 	try
 	{
@@ -1350,7 +1345,7 @@ void HttpRequestTestObjectType::test<13>()
 		req = new HttpRequest();
 		ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
 
-		opts = new HttpOptions();
+        opts = HttpOptions::ptr_t(new HttpOptions());
 		opts->setWantHeaders(true);
 		
 		// Issue a GET that succeeds
@@ -1364,13 +1359,12 @@ void HttpRequestTestObjectType::test<13>()
 													 0,	
 												 0,
 													 opts,
-													 NULL,
-													 &handler);
+                                                     HttpHeaders::ptr_t(),
+                                                     &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// release options
-		opts->release();
-		opts = NULL;
+        opts.reset();
 
 		// Run the notification pump.
 		int count(0);
@@ -1430,11 +1424,7 @@ void HttpRequestTestObjectType::test<13>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (opts)
-		{
-			opts->release();
-			opts = NULL;
-		}
+        opts.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -1460,7 +1450,7 @@ void HttpRequestTestObjectType::test<14>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * opts = NULL;
+	HttpOptions::ptr_t opts;
 	
 	try
 	{
@@ -1475,7 +1465,7 @@ void HttpRequestTestObjectType::test<14>()
 		req = new HttpRequest();
 		ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
 
-		opts = new HttpOptions();
+        opts = HttpOptions::ptr_t(new HttpOptions);
 		opts->setRetries(0);			// Don't retry
 		opts->setTimeout(2);
 		
@@ -1487,8 +1477,8 @@ void HttpRequestTestObjectType::test<14>()
 													 0,
 													 0,
 													 opts,
-													 NULL,
-													 &handler);
+                                                     HttpHeaders::ptr_t(),
+                                                     &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// Run the notification pump.
@@ -1528,8 +1518,7 @@ void HttpRequestTestObjectType::test<14>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 
 		// release options
-		opts->release();
-		opts = NULL;
+        opts.reset();
 		
 		// release the request object
 		delete req;
@@ -1552,11 +1541,7 @@ void HttpRequestTestObjectType::test<14>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (opts)
-		{
-			opts->release();
-			opts = NULL;
-		}
+        opts.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -1609,9 +1594,9 @@ void HttpRequestTestObjectType::test<15>()
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base,
-											NULL,
-											NULL,
-											&handler);
+                                            HttpOptions::ptr_t(),
+                                            HttpHeaders::ptr_t(),
+                                            &handler);
 		ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
 		// Run the notification pump.
@@ -1703,8 +1688,8 @@ void HttpRequestTestObjectType::test<16>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 
 	try
 	{
@@ -1719,7 +1704,7 @@ void HttpRequestTestObjectType::test<16>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 		
 		// Issue a GET that *can* connect
@@ -1776,7 +1761,7 @@ void HttpRequestTestObjectType::test<16>()
 											0U,
 											url_base + "reflect/",
 											options,
-											NULL,
+											HttpHeaders::ptr_t(),
 											&handler);
 		ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
 
@@ -1792,7 +1777,7 @@ void HttpRequestTestObjectType::test<16>()
 		ensure("One handler invocation for request", mHandlerCalls == 1);
 
 		// Do a texture-style fetch
-		headers = new HttpHeaders;
+		headers = HttpHeaders::ptr_t(new HttpHeaders);
 		headers->append("Accept", "image/x-j2c");
 		
 		mStatus = HttpStatus(200);
@@ -1897,17 +1882,8 @@ void HttpRequestTestObjectType::test<16>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -1919,16 +1895,9 @@ void HttpRequestTestObjectType::test<16>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
+        options.reset();
+        headers.reset();
+
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -1960,8 +1929,8 @@ void HttpRequestTestObjectType::test<17>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 	BufferArray * ba = NULL;
 	
 	try
@@ -1977,7 +1946,7 @@ void HttpRequestTestObjectType::test<17>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 
 		// And a buffer array
@@ -2049,7 +2018,7 @@ void HttpRequestTestObjectType::test<17>()
 											 url_base + "reflect/",
 											 ba,
 											 options,
-											 NULL,
+											 HttpHeaders::ptr_t(),
 											 &handler);
 		ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
 		ba->release();
@@ -2095,17 +2064,8 @@ void HttpRequestTestObjectType::test<17>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -2122,17 +2082,10 @@ void HttpRequestTestObjectType::test<17>()
 			ba->release();
 			ba = NULL;
 		}
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
-		delete req;
+        options.reset();
+        headers.reset();
+
+        delete req;
 		HttpRequest::destroyService();
 		throw;
 	}
@@ -2163,8 +2116,8 @@ void HttpRequestTestObjectType::test<18>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 	BufferArray * ba = NULL;
 	
 	try
@@ -2180,7 +2133,7 @@ void HttpRequestTestObjectType::test<18>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+		options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 
 		// And a buffer array
@@ -2253,7 +2206,7 @@ void HttpRequestTestObjectType::test<18>()
 											url_base + "reflect/",
 											ba,
 											options,
-											NULL,
+											HttpHeaders::ptr_t(),
 											&handler);
 		ensure("Valid handle returned for get request", handle != LLCORE_HTTP_HANDLE_INVALID);
 		ba->release();
@@ -2299,17 +2252,8 @@ void HttpRequestTestObjectType::test<18>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -2326,17 +2270,10 @@ void HttpRequestTestObjectType::test<18>()
 			ba->release();
 			ba = NULL;
 		}
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
-		delete req;
+        options.reset();
+        headers.reset();
+
+        delete req;
 		HttpRequest::destroyService();
 		throw;
 	}
@@ -2367,8 +2304,8 @@ void HttpRequestTestObjectType::test<19>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 
 	try
 	{
@@ -2383,11 +2320,11 @@ void HttpRequestTestObjectType::test<19>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 
 		// headers
-		headers = new HttpHeaders;
+		headers = HttpHeaders::ptr_t(new HttpHeaders);
 		headers->append("Keep-Alive", "120");
 		headers->append("Accept-encoding", "deflate");
 		headers->append("Accept", "text/plain");
@@ -2502,17 +2439,8 @@ void HttpRequestTestObjectType::test<19>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -2524,16 +2452,9 @@ void HttpRequestTestObjectType::test<19>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
+        options.reset();
+        headers.reset();
+
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -2565,8 +2486,8 @@ void HttpRequestTestObjectType::test<20>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 	BufferArray * ba = NULL;
 	
 	try
@@ -2582,11 +2503,11 @@ void HttpRequestTestObjectType::test<20>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 
 		// headers
-		headers = new HttpHeaders();
+		headers = HttpHeaders::ptr_t(new HttpHeaders());
 		headers->append("keep-Alive", "120");
 		headers->append("Accept", "text/html");
 		headers->append("content-type", "application/llsd+xml");
@@ -2720,17 +2641,8 @@ void HttpRequestTestObjectType::test<20>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -2747,16 +2659,8 @@ void HttpRequestTestObjectType::test<20>()
 			ba->release();
 			ba = NULL;
 		}
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
+        options.reset();
+        headers.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -2788,8 +2692,8 @@ void HttpRequestTestObjectType::test<21>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * options = NULL;
-	HttpHeaders * headers = NULL;
+	HttpOptions::ptr_t options;
+	HttpHeaders::ptr_t headers;
 	BufferArray * ba = NULL;
 	
 	try
@@ -2805,11 +2709,11 @@ void HttpRequestTestObjectType::test<21>()
 		req = new HttpRequest();
 
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setWantHeaders(true);
 
 		// headers
-		headers = new HttpHeaders;
+		headers = HttpHeaders::ptr_t(new HttpHeaders);
 		headers->append("content-type", "text/plain");
 		headers->append("content-type", "text/html");
 		headers->append("content-type", "application/llsd+xml");
@@ -2937,17 +2841,8 @@ void HttpRequestTestObjectType::test<21>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 	
 		// release options & headers
-		if (options)
-		{
-			options->release();
-		}
-		options = NULL;
-
-		if (headers)
-		{
-			headers->release();
-		}
-		headers = NULL;
+        options.reset();
+        headers.reset();
 		
 		// release the request object
 		delete req;
@@ -2964,16 +2859,8 @@ void HttpRequestTestObjectType::test<21>()
 			ba->release();
 			ba = NULL;
 		}
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
-		if (headers)
-		{
-			headers->release();
-			headers = NULL;
-		}
+        options.reset();
+        headers.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
@@ -3000,13 +2887,13 @@ void HttpRequestTestObjectType::test<22>()
 	mMemTotal = GetMemTotal();
 	mHandlerCalls = 0;
 
-	HttpOptions * options = NULL;
+	HttpOptions::ptr_t options;
 	HttpRequest * req = NULL;
 
 	try
 	{
 		// options set
-		options = new HttpOptions();
+        options = HttpOptions::ptr_t(new HttpOptions());
 		options->setRetries(1);			// Partial_File is retryable and can timeout in here
 
 		// Get singletons created
@@ -3035,8 +2922,8 @@ void HttpRequestTestObjectType::test<22>()
 														 0,
 														 25,
 														 options,
-														 NULL,
-														 &handler);
+                                                         HttpHeaders::ptr_t(),
+                                                         &handler);
 			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 		}
 		
@@ -3067,7 +2954,7 @@ void HttpRequestTestObjectType::test<22>()
 														 0,
 														 25,
 														 options,
-														 NULL,
+														 HttpHeaders::ptr_t(),
 														 &handler);
 			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 		}
@@ -3099,8 +2986,8 @@ void HttpRequestTestObjectType::test<22>()
 														 0,
 														 25,
 														 options,
-														 NULL,
-														 &handler);
+                                                         HttpHeaders::ptr_t(),
+                                                         &handler);
 			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
 		}
 		
@@ -3144,11 +3031,7 @@ void HttpRequestTestObjectType::test<22>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 
 		// release options
-		if (options)
-		{
-			options->release();
-			options = NULL;
-		}
+        options.reset();
 		
 		// release the request object
 		delete req;
@@ -3198,7 +3081,7 @@ void HttpRequestTestObjectType::test<23>()
 	mHandlerCalls = 0;
 
 	HttpRequest * req = NULL;
-	HttpOptions * opts = NULL;
+	HttpOptions::ptr_t opts;
 	
 	try
 	{
@@ -3213,7 +3096,7 @@ void HttpRequestTestObjectType::test<23>()
 		req = new HttpRequest();
 		ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
 
-		opts = new HttpOptions();
+        opts = HttpOptions::ptr_t(new HttpOptions());
 		opts->setRetries(1);			// Retry once only
 		opts->setUseRetryAfter(true);	// Try to parse the retry-after header
 		
@@ -3230,8 +3113,8 @@ void HttpRequestTestObjectType::test<23>()
 														 0,
 														 0,
 														 opts,
-														 NULL,
-														 &handler);
+                                                         HttpHeaders::ptr_t(),
+                                                         &handler);
 
 			std::ostringstream testtag;
 			testtag << "Valid handle returned for 503 request #" << i;
@@ -3277,8 +3160,7 @@ void HttpRequestTestObjectType::test<23>()
 		ensure("Thread actually stopped running", HttpService::isStopped());
 
 		// release options
-		opts->release();
-		opts = NULL;
+        opts.reset();
 		
 		// release the request object
 		delete req;
@@ -3299,11 +3181,7 @@ void HttpRequestTestObjectType::test<23>()
 	catch (...)
 	{
 		stop_thread(req);
-		if (opts)
-		{
-			opts->release();
-			opts = NULL;
-		}
+        opts.reset();
 		delete req;
 		HttpRequest::destroyService();
 		throw;
diff --git a/indra/llcorehttp/tests/test_httpstatus.hpp b/indra/llcorehttp/tests/test_httpstatus.hpp
index 0b379836c9c14945f2d89c5cf25012ba405c13e3..4502d32fe1f0f6c9eb96bb3bebca02442aab3be8 100755
--- a/indra/llcorehttp/tests/test_httpstatus.hpp
+++ b/indra/llcorehttp/tests/test_httpstatus.hpp
@@ -55,77 +55,68 @@ void HttpStatusTestObjectType::test<1>()
 	
 	// auto allocation fine for this
 	HttpStatus status;
-	status.mType = HttpStatus::EXT_CURL_EASY;
-	status.mStatus = 0;
+
+	status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
 	
 	ensure(bool(status));
 	ensure(false == !(status));
 
-	status.mType = HttpStatus::EXT_CURL_MULTI;
-	status.mStatus = 0;
+	status = HttpStatus(HttpStatus::EXT_CURL_MULTI, 0);
 
 	ensure(bool(status));
 	ensure(false == !(status));
-	
-	status.mType = HttpStatus::LLCORE;
-	status.mStatus = HE_SUCCESS;
+
+	status = HttpStatus(HttpStatus::LLCORE, HE_SUCCESS);
 	
 	ensure(bool(status));
 	ensure(false == !(status));
 
-	status.mType = HttpStatus::EXT_CURL_MULTI;
-	status.mStatus = -1;
+	status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -1);
 
 	ensure(false == bool(status));
 	ensure(!(status));
 
-	status.mType = HttpStatus::EXT_CURL_EASY;
-	status.mStatus = CURLE_BAD_DOWNLOAD_RESUME;
+	status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_DOWNLOAD_RESUME);
 
 	ensure(false == bool(status));
 	ensure(!(status));
 }
 
 
-template <> template <>
-void HttpStatusTestObjectType::test<2>()
-{
-	set_test_name("HttpStatus memory structure");
-
-	// Require that an HttpStatus object can be trivially
-	// returned as a function return value in registers.
-	// One should fit in an int on all platforms.
-
-	ensure(sizeof(HttpStatus) <= sizeof(int));
-}
+// template <> template <>
+// void HttpStatusTestObjectType::test<2>()
+// {
+// 	set_test_name("HttpStatus memory structure");
+// 
+// 	// Require that an HttpStatus object can be trivially
+// 	// returned as a function return value in registers.
+// 	// One should fit in an int on all platforms.
+// 
+// 	//ensure(sizeof(HttpStatus) <= sizeof(int));
+// }
 
 
 template <> template <>
-void HttpStatusTestObjectType::test<3>()
+void HttpStatusTestObjectType::test<2>()
 {
 	set_test_name("HttpStatus valid status string conversion");
 	
-	HttpStatus status;
-	status.mType = HttpStatus::EXT_CURL_EASY;
-	status.mStatus = 0;
+	HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 0);
 	std::string msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(msg.empty());
-	
-	status.mType = HttpStatus::EXT_CURL_EASY;
-	status.mStatus = CURLE_BAD_FUNCTION_ARGUMENT;
+
+	status = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_BAD_FUNCTION_ARGUMENT);
 	msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
 
-	status.mType = HttpStatus::EXT_CURL_MULTI;
-	status.mStatus = CURLM_OUT_OF_MEMORY;
+	status = HttpStatus(HttpStatus::EXT_CURL_MULTI, CURLM_OUT_OF_MEMORY);
 	msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
 
-	status.mType = HttpStatus::LLCORE;
-	status.mStatus = HE_SHUTTING_DOWN;
+	status = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
 	msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
@@ -133,32 +124,28 @@ void HttpStatusTestObjectType::test<3>()
 
 
 template <> template <>
-void HttpStatusTestObjectType::test<4>()
+void HttpStatusTestObjectType::test<3>()
 {
 	set_test_name("HttpStatus invalid status string conversion");
 	
-	HttpStatus status;
-	status.mType = HttpStatus::EXT_CURL_EASY;
-	status.mStatus = 32726;
+	HttpStatus status = HttpStatus(HttpStatus::EXT_CURL_EASY, 32726);
 	std::string msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
-	
-	status.mType = HttpStatus::EXT_CURL_MULTI;
-	status.mStatus = -470;
+
+	status = HttpStatus(HttpStatus::EXT_CURL_MULTI, -470);
 	msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
 
-	status.mType = HttpStatus::LLCORE;
-	status.mStatus = 923;
+	status = HttpStatus(HttpStatus::LLCORE, 923);
 	msg = status.toString();
 	// std::cout << "Result:  " << msg << std::endl;
 	ensure(! msg.empty());
 }
 
 template <> template <>
-void HttpStatusTestObjectType::test<5>()
+void HttpStatusTestObjectType::test<4>()
 {
 	set_test_name("HttpStatus equality/inequality testing");
 
@@ -170,62 +157,55 @@ void HttpStatusTestObjectType::test<5>()
 	HttpStatus status2(HttpStatus::EXT_CURL_EASY, HE_SUCCESS);
 	ensure(status1 != status2);
 
-	status1.mType = HttpStatus::LLCORE;
-	status1.mStatus = HE_REPLY_ERROR;
-	status2.mType = HttpStatus::LLCORE;
-	status2.mStatus= HE_SHUTTING_DOWN;
+	status1 = HttpStatus(HttpStatus::LLCORE, HE_REPLY_ERROR);
+	status1 = HttpStatus(HttpStatus::LLCORE, HE_SHUTTING_DOWN);
+
 	ensure(status1 != status2);
 }
 
 template <> template <>
-void HttpStatusTestObjectType::test<6>()
+void HttpStatusTestObjectType::test<5>()
 {
 	set_test_name("HttpStatus basic HTTP status encoding");
 	
 	HttpStatus status;
-	status.mType = 200;
-	status.mStatus = HE_SUCCESS;
+
+	status = HttpStatus(200, HE_SUCCESS);
 	std::string msg = status.toString();
 	ensure(msg.empty());
 	ensure(bool(status));
 
 	// Normally a success but application says error
-	status.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(200, HE_REPLY_ERROR);
 	msg = status.toString();
 	ensure(! msg.empty());
 	ensure(! bool(status));
 	ensure(status.toULong() > 1UL);				// Biggish number, not a bool-to-ulong
 
 	// Same statuses with distinct success/fail are distinct
-	status.mType = 200;
-	status.mStatus = HE_SUCCESS;
+	status = HttpStatus(200, HE_SUCCESS);
 	HttpStatus status2(200, HE_REPLY_ERROR);
 	ensure(status != status2);
 
 	// Normally an error but application says okay
-	status.mType = 406;
-	status.mStatus = HE_SUCCESS;
+	status = HttpStatus(406, HE_SUCCESS);
 	msg = status.toString();
 	ensure(msg.empty());
 	ensure(bool(status));
 
 	// Different statuses but both successful are distinct
-	status.mType = 200;
-	status.mStatus = HE_SUCCESS;
-	status2.mType = 201;
-	status2.mStatus = HE_SUCCESS;
+	status = HttpStatus(200, HE_SUCCESS);
+	status2 = HttpStatus(201, HE_SUCCESS);
 	ensure(status != status2);
 
 	// Different statuses but both failed are distinct
-	status.mType = 200;
-	status.mStatus = HE_REPLY_ERROR;
-	status2.mType = 201;
-	status2.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(200, HE_REPLY_ERROR);
+	status2 = HttpStatus(201, HE_REPLY_ERROR);
 	ensure(status != status2);
 }
 
 template <> template <>
-void HttpStatusTestObjectType::test<7>()
+void HttpStatusTestObjectType::test<6>()
 {
 	set_test_name("HttpStatus HTTP status text strings");
 
@@ -234,34 +214,30 @@ void HttpStatusTestObjectType::test<7>()
 	ensure(! msg.empty());				// Should be something
 	ensure(msg == "Continue");
 
-	status.mStatus = HE_SUCCESS;
+	status = HttpStatus(200, HE_SUCCESS);
 	msg = status.toString();
 	ensure(msg.empty());				// Success is empty
 
-	status.mType = 199;
-	status.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(199, HE_REPLY_ERROR);
 	msg = status.toString();
 	ensure(msg == "Unknown error");
 
-	status.mType = 505;					// Last defined string
-	status.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(505, HE_REPLY_ERROR);
 	msg = status.toString();
 	ensure(msg == "HTTP Version not supported");
 
-	status.mType = 506;					// One beyond
-	status.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(506, HE_REPLY_ERROR);
 	msg = status.toString();
 	ensure(msg == "Unknown error");
 
-	status.mType = 999;					// Last HTTP status
-	status.mStatus = HE_REPLY_ERROR;
+	status = HttpStatus(999, HE_REPLY_ERROR);
 	msg = status.toString();
 	ensure(msg == "Unknown error");
 }
 
 
 template <> template <>
-void HttpStatusTestObjectType::test<8>()
+void HttpStatusTestObjectType::test<7>()
 {
 	set_test_name("HttpStatus toHex() nominal function");
 	
@@ -273,7 +249,7 @@ void HttpStatusTestObjectType::test<8>()
 
 
 template <> template <>
-void HttpStatusTestObjectType::test<9>()
+void HttpStatusTestObjectType::test<8>()
 {
 	set_test_name("HttpStatus toTerseString() nominal function");
 	
diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt
index ba4e34d92b0e04f3f37eb8962b3914c44fe7b3a9..da23b46b7b1ad99b45ad2a4bd7205fbbef8c2fd2 100755
--- a/indra/llcrashlogger/CMakeLists.txt
+++ b/indra/llcrashlogger/CMakeLists.txt
@@ -3,6 +3,7 @@
 project(llcrashlogger)
 
 include(00-Common)
+include(LLCoreHttp)
 include(LLCommon)
 include(LLMath)
 include(LLMessage)
@@ -10,6 +11,7 @@ include(LLVFS)
 include(LLXML)
 
 include_directories(
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
     ${LLMESSAGE_INCLUDE_DIRS}
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 7a97c16ea7048c6a0b1c86ccc64352795f2b8c7b..6fd4579876f2ec5b8ad279678f0156d3129d19d0 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -40,38 +40,45 @@
 #include "lldir.h"
 #include "llfile.h"
 #include "llsdserialize.h"
-#include "lliopipe.h"
-#include "llpumpio.h"
-#include "llhttpclient.h"
 #include "llsdserialize.h"
 #include "llproxy.h"
- 
-LLPumpIO* gServicePump = NULL;
+#include "llcorehttputil.h"
+#include "llhttpsdhandler.h"
+#include "httpcommon.h"
+#include "httpresponse.h"
+
+#include <curl/curl.h>
+#include <openssl/crypto.h>
+
 BOOL gBreak = false;
 BOOL gSent = false;
 
-class LLCrashLoggerResponder : public LLHTTPClient::Responder
+int LLCrashLogger::ssl_mutex_count = 0;
+LLCoreInt::HttpMutex ** LLCrashLogger::ssl_mutex_list = NULL;
+
+class LLCrashLoggerHandler : public LLHttpSDHandler
 {
-	LOG_CLASS(LLCrashLoggerResponder);
+    LOG_CLASS(LLCrashLoggerHandler);
 public:
-	LLCrashLoggerResponder() 
-	{
-	}
+    LLCrashLoggerHandler() {}
 
 protected:
-	virtual void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-		gBreak = true;
-	}
+    virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+    virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
 
-	virtual void httpSuccess()
-	{
-		gBreak = true;
-		gSent = true;
-	}
 };
 
+void LLCrashLoggerHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
+{
+    gBreak = true;
+    gSent = true;
+}
+
+void LLCrashLoggerHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
+{
+    gBreak = true;
+}
+
 LLCrashLogger::LLCrashLogger() :
 	mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND),
 	mCrashInPreviousExec(false),
@@ -207,11 +214,13 @@ void LLCrashLogger::gatherFiles()
 		mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString();
 		if(mDebugLog.has("CAFilename"))
 		{
-			LLCurl::setCAFile(mDebugLog["CAFilename"].asString());
+            LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE,
+                LLCore::HttpRequest::GLOBAL_POLICY_ID, mDebugLog["CAFilename"].asString(), NULL);
 		}
 		else
 		{
-			LLCurl::setCAFile(gDirUtilp->getCAFile());
+            LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE,
+                LLCore::HttpRequest::GLOBAL_POLICY_ID, gDirUtilp->getCAFile(), NULL);
 		}
 
 		LL_INFOS() << "Using log file from debug log " << mFileMap["SecondLifeLog"] << LL_ENDL;
@@ -220,7 +229,8 @@ void LLCrashLogger::gatherFiles()
 	else
 	{
 		// Figure out the filename of the second life log
-		LLCurl::setCAFile(gDirUtilp->getCAFile());
+        LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_CA_FILE,
+            LLCore::HttpRequest::GLOBAL_POLICY_ID, gDirUtilp->getCAFile(), NULL);
         
 		mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
         mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
@@ -389,14 +399,23 @@ bool LLCrashLogger::saveCrashBehaviorSetting(S32 crash_behavior)
 
 bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg, int retries, int timeout)
 {
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
 	gBreak = false;
+    httpOpts->setTimeout(timeout);
+
 	for(int i = 0; i < retries; ++i)
 	{
 		updateApplication(llformat("%s, try %d...", msg.c_str(), i+1));
-		LLHTTPClient::post(host, data, new LLCrashLoggerResponder(), timeout);
-		while(!gBreak)
+
+        LLCoreHttpUtil::requestPostWithLLSD(httpRequest.get(), LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
+            host, data, httpOpts, LLCore::HttpHeaders::ptr_t(), new LLCrashLoggerHandler);
+
+        while(!gBreak)
 		{
 			updateApplication(); // No new message, just pump the IO
+            httpRequest->update(0L);
 		}
 		if(gSent)
 		{
@@ -510,14 +529,12 @@ bool LLCrashLogger::sendCrashLogs()
 
 void LLCrashLogger::updateApplication(const std::string& message)
 {
-	gServicePump->pump();
-    gServicePump->callback();
 	if (!message.empty()) LL_INFOS() << message << LL_ENDL;
 }
 
 bool LLCrashLogger::init()
 {
-	LLCurl::initClass(false);
+    LLCore::LLHttp::initialize();
 
 	// We assume that all the logs we're looking for reside on the current drive
 	gDirUtilp->initAppDirs("SecondLife");
@@ -576,16 +593,74 @@ bool LLCrashLogger::init()
 		return false;
 	}
     
-	gServicePump = new LLPumpIO(gAPRPoolp);
-	gServicePump->prime(gAPRPoolp);
-	LLHTTPClient::setPump(*gServicePump);
- 	
+    init_curl();
+    LLCore::HttpRequest::createService();
+    LLCore::HttpRequest::startThread();
+
 	return true;
 }
 
 // For cleanup code common to all platforms.
 void LLCrashLogger::commonCleanup()
 {
+    term_curl();
 	LLError::logToFile("");   //close crashreport.log
 	LLProxy::cleanupClass();
 }
+
+void LLCrashLogger::init_curl()
+{
+    curl_global_init(CURL_GLOBAL_ALL);
+
+    ssl_mutex_count = CRYPTO_num_locks();
+    if (ssl_mutex_count > 0)
+    {
+        ssl_mutex_list = new LLCoreInt::HttpMutex *[ssl_mutex_count];
+
+        for (int i(0); i < ssl_mutex_count; ++i)
+        {
+            ssl_mutex_list[i] = new LLCoreInt::HttpMutex;
+        }
+
+        CRYPTO_set_locking_callback(ssl_locking_callback);
+        CRYPTO_set_id_callback(ssl_thread_id_callback);
+    }
+}
+
+
+void LLCrashLogger::term_curl()
+{
+    CRYPTO_set_locking_callback(NULL);
+    for (int i(0); i < ssl_mutex_count; ++i)
+    {
+        delete ssl_mutex_list[i];
+    }
+    delete[] ssl_mutex_list;
+}
+
+
+unsigned long LLCrashLogger::ssl_thread_id_callback(void)
+{
+#if LL_WINDOWS
+    return (unsigned long)GetCurrentThread();
+#else
+    return (unsigned long)pthread_self();
+#endif
+}
+
+
+void LLCrashLogger::ssl_locking_callback(int mode, int type, const char * /* file */, int /* line */)
+{
+    if (type >= 0 && type < ssl_mutex_count)
+    {
+        if (mode & CRYPTO_LOCK)
+        {
+            ssl_mutex_list[type]->lock();
+        }
+        else
+        {
+            ssl_mutex_list[type]->unlock();
+        }
+    }
+}
+
diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h
index a06bf1d6ac24dd53f99a3d7e48aa0bb8f4021bcf..f5383daefc1c5104ac0b99cf5480f30dd8fe9003 100755
--- a/indra/llcrashlogger/llcrashlogger.h
+++ b/indra/llcrashlogger/llcrashlogger.h
@@ -34,6 +34,7 @@
 #include "llsd.h"
 #include "llcontrol.h"
 #include "llcrashlock.h"
+#include "_mutex.h"
 
 // Crash reporter behavior
 const S32 CRASH_BEHAVIOR_ASK = 0;
@@ -66,6 +67,11 @@ class LLCrashLogger : public LLApp
 	bool readMinidump(std::string minidump_path);
 
 protected:
+    static void init_curl();
+    static void term_curl();
+    static unsigned long ssl_thread_id_callback(void);
+    static void ssl_locking_callback(int mode, int type, const char * file, int line);
+
 	S32 mCrashBehavior;
 	BOOL mCrashInPreviousExec;
 	std::map<std::string, std::string> mFileMap;
@@ -78,6 +84,10 @@ class LLCrashLogger : public LLApp
 	LLSD mDebugLog;
 	bool mSentCrashLogs;
     LLCrashLock mKeyMaster;
+
+    static int ssl_mutex_count;
+    static LLCoreInt::HttpMutex ** ssl_mutex_list;
+
 };
 
 #endif //LLCRASHLOGGER_H
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index 0a1f93bd8033807f8ed4b4373b551bddf840ee24..68dd00d88060b50086c982a02e7a7fd521131608 100755
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -4,6 +4,7 @@ project(llinventory)
 
 include(00-Common)
 include(LLCommon)
+include(LLCoreHttp)
 include(LLMath)
 include(LLMessage)
 include(LLVFS)
@@ -71,7 +72,7 @@ if (LL_TESTS)
     LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
 
     #set(TEST_DEBUG on)
-    set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+    set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLCOREHTTP_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
     LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
     LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
 endif (LL_TESTS)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index c2198b91a7b7a7f2fa12d91f03582669af6856af..4703e6cf1a746727fd5d8f5d4d3d2c5d9b93e5cc 100755
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -6072,7 +6072,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
 
 	if (new_verts > mNumAllocatedVertices)
 	{ 
-		//double buffer size on expansion
+		// double buffer size on expansion
 		new_verts *= 2;
 
 		S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF;
@@ -6088,18 +6088,21 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
 		mNormals = mPositions+new_verts;
 		mTexCoords = (LLVector2*) (mNormals+new_verts);
 
-	//positions
-		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
-	
-	//normals
-		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
+		if (old_buf != NULL)
+		{
+			// copy old positions into new buffer
+			LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize);
 
-	//tex coords
-		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
+			// normals
+			LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize);
 
-	//just clear tangents
-	ll_aligned_free_16(mTangents);
-	mTangents = NULL;
+			// tex coords
+			LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size);
+		}
+
+		// just clear tangents
+		ll_aligned_free_16(mTangents);
+		mTangents = NULL;
 		ll_aligned_free<64>(old_buf);
 
 		mNumAllocatedVertices = new_verts;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index c8476f689796cb1aeff0a06097f9d3f05d430227..625f7cff02bf78272bd30d8f070de280620e7128 100755
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -968,6 +968,7 @@ class LLVolume : public LLRefCount
 	~LLVolume(); // use unref
 
 public:
+	typedef std::vector<LLVolumeFace> face_list_t;
 		
 	struct FaceParams
 	{
@@ -1041,6 +1042,10 @@ class LLVolume : public LLRefCount
 																				// conversion if *(LLVolume*) to LLVolume&
 	const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
 	
+	LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
+
+	face_list_t& getVolumeFaces() { return mVolumeFaces; }
+
 	U32					mFaceMask;			// bit array of which faces exist in this volume
 	LLVector3			mLODScaleBias;		// vector for biasing LOD based on scale
 	
@@ -1080,7 +1085,6 @@ class LLVolume : public LLRefCount
 	
 	
 	BOOL mGenerateSingleFace;
-	typedef std::vector<LLVolumeFace> face_list_t;
 	face_list_t mVolumeFaces;
 
 public:
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index 6a1b4143cfd64e9474f51e94645d54e2c7cda146..d89c482804d760ec49504fb713b959d590bddca4 100755
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -274,6 +274,19 @@ const LLMatrix4&	LLMatrix4::invert(void)
 	return *this;
 }
 
+// Convenience func for simplifying comparison-heavy code by
+// intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f
+//
+void LLMatrix4::condition(void)
+{
+	U32 i;
+	U32 j;
+	for (i = 0; i < 3;i++)
+		for (j = 0; j < 3;j++)
+			mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON)
+							  && (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j];
+}
+
 LLVector4 LLMatrix4::getFwdRow4() const
 {
 	return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]);
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index a7dce10397839e4ea21c88d59f4689d29f9193ed..a77c5bc76d11111149559b0f3552823ac9164f9f 100755
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -180,6 +180,11 @@ class LLMatrix4
 	const LLMatrix4& setTranslation(const LLVector4 &translation);
 	const LLMatrix4& setTranslation(const LLVector3 &translation);
 
+	// Convenience func for simplifying comparison-heavy code by
+	// intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0
+	//
+	void condition(void);
+
 	///////////////////////////
 	//
 	// Get properties of a matrix
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 0a308fbf10170db13ff669e07589e79b60dcd052..78c84f366a1d95b4a816e5a70a6ccab635386f8f 100755
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -14,6 +14,7 @@ include(LLAddBuildTest)
 include(Python)
 include(Tut)
 include(Python)
+include(JsonCpp)
 
 include_directories (${CMAKE_CURRENT_SOURCE_DIR})
 
@@ -23,11 +24,10 @@ include_directories(
     ${LLMATH_INCLUDE_DIRS}
     ${LLMESSAGE_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
+    ${JSONCPP_INCLUDE_DIR}
     )
 
 set(llmessage_SOURCE_FILES
-    llares.cpp
-    llareslistener.cpp
     llassetstorage.cpp
     llavatarname.cpp
     llavatarnamecache.cpp
@@ -38,19 +38,15 @@ set(llmessage_SOURCE_FILES
     llchainio.cpp
     llcircuit.cpp
     llclassifiedflags.cpp
+    llcoproceduremanager.cpp
     llcorehttputil.cpp
-    llcurl.cpp
     lldatapacker.cpp
     lldispatcher.cpp
     llexperiencecache.cpp
     llfiltersd2xmlrpc.cpp
     llhost.cpp
-    llhttpassetstorage.cpp
-    llhttpclient.cpp
-    llhttpclientadapter.cpp
-    llhttpconstants.cpp
     llhttpnode.cpp
-    llhttpsender.cpp
+    llhttpsdhandler.cpp
     llinstantmessage.cpp
     lliobuffer.cpp
     lliohttpserver.cpp
@@ -74,11 +70,8 @@ set(llmessage_SOURCE_FILES
     llpumpio.cpp
     llsdappservices.cpp
     llsdhttpserver.cpp
-    llsdmessage.cpp
     llsdmessagebuilder.cpp
     llsdmessagereader.cpp
-    llsdrpcclient.cpp
-    llsdrpcserver.cpp
     llservicebuilder.cpp
     llservice.cpp
     llstoredmessage.cpp
@@ -92,7 +85,6 @@ set(llmessage_SOURCE_FILES
     lltransfertargetfile.cpp
     lltransfertargetvfile.cpp
     lltrustedmessageservice.cpp
-    llurlrequest.cpp
     lluseroperation.cpp
     llxfer.cpp
     llxfer_file.cpp
@@ -115,8 +107,6 @@ set(llmessage_SOURCE_FILES
 set(llmessage_HEADER_FILES
     CMakeLists.txt
 
-    llares.h
-    llareslistener.h
     llassetstorage.h
     llavatarname.h
     llavatarnamecache.h
@@ -128,8 +118,8 @@ set(llmessage_HEADER_FILES
     llcipher.h
     llcircuit.h
     llclassifiedflags.h
+    llcoproceduremanager.h
     llcorehttputil.h
-    llcurl.h
     lldatapacker.h
     lldbstrings.h
     lldispatcher.h
@@ -139,14 +129,9 @@ set(llmessage_HEADER_FILES
     llfiltersd2xmlrpc.h
     llfollowcamparams.h
     llhost.h
-    llhttpassetstorage.h
-    llhttpclient.h
-    llhttpclientinterface.h
-    llhttpclientadapter.h
-    llhttpconstants.h
     llhttpnode.h
     llhttpnodeadapter.h
-    llhttpsender.h
+    llhttpsdhandler.h
     llinstantmessage.h
     llinvite.h
     lliobuffer.h
@@ -176,11 +161,8 @@ set(llmessage_HEADER_FILES
     llregionhandle.h
     llsdappservices.h
     llsdhttpserver.h
-    llsdmessage.h
     llsdmessagebuilder.h
     llsdmessagereader.h
-    llsdrpcclient.h
-    llsdrpcserver.h
     llservice.h
     llservicebuilder.h
     llstoredmessage.h
@@ -196,7 +178,6 @@ set(llmessage_HEADER_FILES
     lltransfertargetfile.h
     lltransfertargetvfile.h
     lltrustedmessageservice.h
-    llurlrequest.h
     lluseroperation.h
     llvehicleparams.h
     llxfer.h
@@ -226,12 +207,16 @@ target_link_libraries(
   llmessage
   ${CURL_LIBRARIES}
   ${LLCOMMON_LIBRARIES}
-  ${LLVFS_LIBRARES}
+  ${LLVFS_LIBRARIES}
   ${LLMATH_LIBRARIES}
-  ${CARES_LIBRARIES}
+  ${JSONCPP_LIBRARIES}
   ${OPENSSL_LIBRARIES}
   ${CRYPTO_LIBRARIES}
   ${XMLRPCEPI_LIBRARIES}
+  ${LLCOREHTTP_LIBRARIES}
+  ${BOOST_COROUTINE_LIBRARY}
+  ${BOOST_CONTEXT_LIBRARY}
+  ${BOOST_SYSTEM_LIBRARY}
   )
 
 # tests
@@ -243,36 +228,25 @@ if (LL_TESTS)
     )
   LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
 
+  
   #    set(TEST_DEBUG on)
+  
   set(test_libs
-    ${CURL_LIBRARIES}
-    ${LLMESSAGE_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
+    ${CURL_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
-      ${GOOGLEMOCK_LIBRARIES}
-    )
-
-  LL_ADD_INTEGRATION_TEST(
-    llsdmessage
-    "llsdmessage.cpp"
-    "${test_libs}"
-    ${PYTHON_EXECUTABLE}
-    "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
-    )
-
-  LL_ADD_INTEGRATION_TEST(
-    llhttpclient
-    "llhttpclient.cpp"
-    "${test_libs}"
-    ${PYTHON_EXECUTABLE}
-    "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
+    ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
+    ${JSONCPP_LIBRARIES}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${GOOGLEMOCK_LIBRARIES}
     )
 
-  LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
+  #LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
 endif (LL_TESTS)
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
deleted file mode 100755
index 9f90ae1544782ad11574a1545633d4a619e65187..0000000000000000000000000000000000000000
--- a/indra/llmessage/llares.cpp
+++ /dev/null
@@ -1,839 +0,0 @@
-/** 
- * @file llares.cpp
- * @author Bryan O'Sullivan
- * @date 2007-08-15
- * @brief Wrapper for asynchronous DNS lookups.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llares.h"
-
-#include <ares_dns.h>
-#include <ares_version.h>
-
-#include "apr_portable.h"
-#include "apr_network_io.h"
-#include "apr_poll.h"
-
-#include "llapr.h"
-#include "llareslistener.h"
-
-#if defined(LL_WINDOWS)
-#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
-# define ns_c_in 1
-# define NS_HFIXEDSZ     12      /* #/bytes of fixed data in header */
-# define NS_QFIXEDSZ     4       /* #/bytes of fixed data in query */
-# define NS_RRFIXEDSZ    10      /* #/bytes of fixed data in r record */
-#else
-# include <arpa/nameser.h>
-#endif
-
-LLAres::HostResponder::~HostResponder()
-{
-}
-
-void LLAres::HostResponder::hostResult(const hostent *ent)
-{
-	LL_INFOS() << "LLAres::HostResponder::hostResult not implemented" << LL_ENDL;
-}
-
-void LLAres::HostResponder::hostError(int code)
-{
-	LL_INFOS() << "LLAres::HostResponder::hostError " << code << ": "
-			<< LLAres::strerror(code) << LL_ENDL;
-}
-
-LLAres::NameInfoResponder::~NameInfoResponder()
-{
-}
-
-void LLAres::NameInfoResponder::nameInfoResult(const char *node,
-											   const char *service)
-{
-	LL_INFOS() << "LLAres::NameInfoResponder::nameInfoResult not implemented"
-			<< LL_ENDL;
-}
-
-void LLAres::NameInfoResponder::nameInfoError(int code)
-{
-	LL_INFOS() << "LLAres::NameInfoResponder::nameInfoError " << code << ": "
-			<< LLAres::strerror(code) << LL_ENDL;
-}
-
-LLAres::QueryResponder::~QueryResponder()
-{
-}
-
-void LLAres::QueryResponder::queryResult(const char *buf, size_t len)
-{
-	LL_INFOS() << "LLAres::QueryResponder::queryResult not implemented"
-			<< LL_ENDL;
-}
-
-void LLAres::QueryResponder::queryError(int code)
-{
-	LL_INFOS() << "LLAres::QueryResponder::queryError " << code << ": "
-			<< LLAres::strerror(code) << LL_ENDL;
-}
-
-LLAres::LLAres() :
-    chan_(NULL),
-    mInitSuccess(false)
-{
-	if (ares_library_init( ARES_LIB_INIT_ALL ) != ARES_SUCCESS ||
-		ares_init(&chan_) != ARES_SUCCESS)
-	{
-		LL_WARNS() << "Could not succesfully initialize ares!" << LL_ENDL;
-		return;
-	}
-
-	mListener = boost::shared_ptr< LLAresListener >(new LLAresListener(this));
-
-	mInitSuccess = true;
-}
-
-LLAres::~LLAres()
-{
-	ares_destroy(chan_);
-	ares_library_cleanup();
-}
-
-void LLAres::cancel()
-{
-	ares_cancel(chan_);
-}
-
-static void host_callback_1_5(void *arg, int status, int timeouts,
-							  struct hostent *ent)
-{
-	LLPointer<LLAres::HostResponder> *resp =
-		(LLPointer<LLAres::HostResponder> *) arg;
-
-	if (status == ARES_SUCCESS)
-	{
-		(*resp)->hostResult(ent);
-	} else {
-		(*resp)->hostError(status);
-	}
-
-	delete resp;
-}
-
-#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
-static void host_callback(void *arg, int status, struct hostent *ent)
-{
-	host_callback_1_5(arg, status, 0, ent);
-}
-#else
-# define host_callback host_callback_1_5
-#endif
-
-void LLAres::getHostByName(const char *name, HostResponder *resp,
-						   int family)
-{
-	ares_gethostbyname(chan_, name, family, host_callback,
-					   new LLPointer<LLAres::HostResponder>(resp));
-}
-	
-void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp)
-{
-	search(name, RES_SRV, resp);
-}
-	
-void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp)
-{	
-	if (resp && uri.size())
-	{
-		LLURI* pURI = new LLURI(uri);
-
-		resp->mUri = *pURI;
-
-		delete pURI;
-
-		if (!resp->mUri.scheme().size() || !resp->mUri.hostName().size())
-		{
-			return;
-		}
-
-		//LL_INFOS() << "LLAres::rewriteURI (" << uri << ") search: '" << "_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName() << "'" << LL_ENDL;
-
-		search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), RES_SRV, resp);
-
-		
-	}
-}
-
-LLQueryResponder::LLQueryResponder()
-	: LLAres::QueryResponder(),
-	  mResult(ARES_ENODATA),
-	  mType(RES_INVALID)
-{
-}
-
-int LLQueryResponder::parseRR(const char *buf, size_t len, const char *&pos,
-							  LLPointer<LLDnsRecord> &r)
-{
-	std::string rrname;
-	size_t enclen;
-	int ret;
-
-	// RR name.
-
-	ret = LLAres::expandName(pos, buf, len, rrname, enclen);
-	if (ret != ARES_SUCCESS)
-	{
-		return ret;
-	}
-		
-	pos += enclen;
-
-	if (pos + NS_RRFIXEDSZ > buf + len)
-	{
-		return ARES_EBADRESP;
-	}
-
-	int rrtype = DNS_RR_TYPE(pos);
-	int rrclass = DNS_RR_CLASS(pos);
-	int rrttl = DNS_RR_TTL(pos);
-	int rrlen = DNS_RR_LEN(pos);
-		
-	if (rrclass != ns_c_in)
-	{
-		return ARES_EBADRESP;
-	}
-
-	pos += NS_RRFIXEDSZ;
-
-	if (pos + rrlen > buf + len)
-	{
-		return ARES_EBADRESP;
-	}
-
-	switch (rrtype)
-	{
-	case RES_A:
-		r = new LLARecord(rrname, rrttl);
-		break;
-	case RES_NS:
-		r = new LLNsRecord(rrname, rrttl);
-		break;
-	case RES_CNAME:
-		r = new LLCnameRecord(rrname, rrttl);
-		break;
-	case RES_PTR:
-		r = new LLPtrRecord(rrname, rrttl);
-		break;
-	case RES_AAAA:
-		r = new LLAaaaRecord(rrname, rrttl);
-		break;
-	case RES_SRV:
-		r = new LLSrvRecord(rrname, rrttl);
-		break;
-	default:
-		LL_INFOS() << "LLQueryResponder::parseRR got unknown RR type " << rrtype
-				<< LL_ENDL;
-		return ARES_EBADRESP;
-	}
-
-	ret = r->parse(buf, len, pos, rrlen);
-
-	if (ret == ARES_SUCCESS)
-	{
-		pos += rrlen;
-	} else {
-		r = NULL;
-	}
-		
-	return ret;
-}
-
-int LLQueryResponder::parseSection(const char *buf, size_t len,
-								   size_t count, const char *&pos,
-								   dns_rrs_t &rrs)
-{
-	int ret = ARES_SUCCESS;
-	
-	for (size_t i = 0; i < count; i++)
-	{
-		LLPointer<LLDnsRecord> r;
-		ret = parseRR(buf, len, pos, r);
-		if (ret != ARES_SUCCESS)
-		{
-			break;
-		}
-		rrs.push_back(r);
-	}
-
-	return ret;
-}
-
-void LLQueryResponder::queryResult(const char *buf, size_t len)
-{
-	const char *pos = buf;
-	int qdcount = DNS_HEADER_QDCOUNT(pos);
-	int ancount = DNS_HEADER_ANCOUNT(pos);
-	int nscount = DNS_HEADER_NSCOUNT(pos);
-	int arcount = DNS_HEADER_ARCOUNT(pos);
-	int ret;
-
-	if (qdcount == 0 || ancount + nscount + arcount == 0)
-	{
-		ret = ARES_ENODATA;
-		goto bail;
-	}
-
-	pos += NS_HFIXEDSZ;
-
-	for (int i = 0; i < qdcount; i++)
-	{
-		std::string ignore;
-		size_t enclen;
-
-		ret = LLAres::expandName(pos, buf, len, i == 0 ? mQuery : ignore,
-								 enclen);
-		if (ret != ARES_SUCCESS)
-		{
-			goto bail;
-		}
-
-		pos += enclen;
-
-		if (i == 0)
-		{
-			int t = DNS_QUESTION_TYPE(pos);
-			switch (t)
-			{
-			case RES_A:
-			case RES_NS:
-			case RES_CNAME:
-			case RES_PTR:
-			case RES_AAAA:
-			case RES_SRV:
-				mType = (LLResType) t;
-				break;
-			default:
-				LL_INFOS() << "Cannot grok query type " << t << LL_ENDL;
-				ret = ARES_EBADQUERY;
-				goto bail;
-			}
-		}
-
-		pos += NS_QFIXEDSZ;
-		if (pos > buf + len)
-		{
-			ret = ARES_EBADRESP;
-			goto bail;
-		}
-	}
-	
-	ret = parseSection(buf, len, ancount, pos, mAnswers);
-	if (ret != ARES_SUCCESS)
-	{
-		goto bail;
-	}
-
-	ret = parseSection(buf, len, nscount, pos, mAuthorities);
-	if (ret != ARES_SUCCESS)
-	{
-		goto bail;
-	}
-
-	ret = parseSection(buf, len, arcount, pos, mAdditional);
-
-bail:
-	mResult = ret;
-	if (mResult == ARES_SUCCESS)
-	{
-		querySuccess();
-	} else {
-		queryError(mResult);
-	}
-}
-
-void LLQueryResponder::querySuccess()
-{
-	LL_INFOS() << "LLQueryResponder::queryResult not implemented" << LL_ENDL;
-}
-
-void LLAres::SrvResponder::querySuccess()
-{
-	if (mType == RES_SRV)
-	{
-		srvResult(mAnswers);
-	} else {
-		srvError(ARES_EBADRESP);
-	}
-}
-
-void LLAres::SrvResponder::queryError(int code)
-{
-	srvError(code);
-}
-
-void LLAres::SrvResponder::srvResult(const dns_rrs_t &ents)
-{
-	LL_INFOS() << "LLAres::SrvResponder::srvResult not implemented" << LL_ENDL;
-
-	for (size_t i = 0; i < ents.size(); i++)
-	{
-		const LLSrvRecord *s = (const LLSrvRecord *) ents[i].get();
-
-		LL_INFOS() << "[" << i << "] " << s->host() << ":" << s->port()
-				<< " priority " << s->priority()
-				<< " weight " << s->weight()
-				<< LL_ENDL;
-	}
-}
-
-void LLAres::SrvResponder::srvError(int code)
-{
-	LL_INFOS() << "LLAres::SrvResponder::srvError " << code << ": "
-			<< LLAres::strerror(code) << LL_ENDL;
-}
-
-static void nameinfo_callback_1_5(void *arg, int status, int timeouts,
-								  char *node, char *service)
-{
-	LLPointer<LLAres::NameInfoResponder> *resp =
-		(LLPointer<LLAres::NameInfoResponder> *) arg;
-
-	if (status == ARES_SUCCESS)
-	{
-		(*resp)->nameInfoResult(node, service);
-	} else {
-		(*resp)->nameInfoError(status);
-	}
-
-	delete resp;
-}
-
-#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
-static void nameinfo_callback(void *arg, int status, char *node, char *service)
-{
-	nameinfo_callback_1_5(arg, status, 0, node, service);
-}
-#else
-# define nameinfo_callback nameinfo_callback_1_5
-#endif
-
-void LLAres::getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
-						 NameInfoResponder *resp)
-{
-	ares_getnameinfo(chan_, &sa, salen, flags, nameinfo_callback,
-					 new LLPointer<NameInfoResponder>(resp));
-}
-
-static void search_callback_1_5(void *arg, int status, int timeouts,
-								unsigned char *abuf, int alen)
-{
-	LLPointer<LLAres::QueryResponder> *resp =
-		(LLPointer<LLAres::QueryResponder> *) arg;
-
-	if (status == ARES_SUCCESS)
-	{
-		(*resp)->queryResult((const char *) abuf, alen);
-	} else {
-		(*resp)->queryError(status);
-	}
-
-	delete resp;
-}
-
-#if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
-static void search_callback(void *arg, int status, unsigned char *abuf,
-							int alen)
-{
-	search_callback_1_5(arg, status, 0, abuf, alen);
-}
-#else
-# define search_callback search_callback_1_5
-#endif
-
-void LLAres::search(const std::string &query, LLResType type,
-					QueryResponder *resp)
-{
-	ares_search(chan_, query.c_str(), ns_c_in, type, search_callback,
-				new LLPointer<QueryResponder>(resp));
-}
-
-bool LLAres::process(U64 timeout)
-{
-	if (!gAPRPoolp)
-	{
-		ll_init_apr();
-	}
-
-	ares_socket_t socks[ARES_GETSOCK_MAXNUM];
-	apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
-	apr_int32_t nsds = 0;	
-	int nactive = 0;
-	int bitmask;
-
-	bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM);
-
-	if (bitmask == 0)
-	{
-		return nsds > 0;
-	}
-
-	apr_status_t status;
-	LLAPRPool pool;
-	status = pool.getStatus() ;
-	ll_apr_assert_status(status);
-
-	for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
-	{
-		if (ARES_GETSOCK_READABLE(bitmask, i))
-		{
-			aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR;
-		}
-		else if (ARES_GETSOCK_WRITABLE(bitmask, i))
-		{
-			aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR;
-		} else {
-			continue;
-		}
-
-		apr_socket_t *aprSock = NULL;
-
-		status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool());
-		if (status != APR_SUCCESS)
-		{
-			ll_apr_warn_status(status);
-			return nsds > 0;
-		}
-
-		aprFds[nactive].desc.s = aprSock;
-		aprFds[nactive].desc_type = APR_POLL_SOCKET;
-		aprFds[nactive].p = pool.getAPRPool();
-		aprFds[nactive].rtnevents = 0;
-		aprFds[nactive].client_data = &socks[i];
-
-		nactive++;
-	}
-
-	if (nactive > 0)
-	{
-		status = apr_poll(aprFds, nactive, &nsds, timeout);
-
-		if (status != APR_SUCCESS && status != APR_TIMEUP)
-		{
-			ll_apr_warn_status(status);
-		}
-
-		for (int i = 0; i < nactive; i++)
-		{
-			int evts = aprFds[i].rtnevents;
-			int ifd = (evts & (APR_POLLIN | APR_POLLERR))
-				? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
-			int ofd = (evts & (APR_POLLOUT | APR_POLLERR))
-				? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
-					
-			ares_process_fd(chan_, ifd, ofd);
-		}
-	}
-
-	return nsds > 0;
-}
-
-bool LLAres::processAll()
-{
-	bool anyProcessed = false, ret;
-
-	do {
-		timeval tv;
-
-		ret = ares_timeout(chan_, NULL, &tv) != NULL;
-
-		if (ret)
-		{
-			ret = process(tv.tv_sec * 1000000LL + tv.tv_usec);
-			anyProcessed |= ret;
-		}
-	} while (ret);
-
-	return anyProcessed;
-}
-
-int LLAres::expandName(const char *encoded, const char *abuf, size_t alen,
-					   std::string &s, size_t &enclen)
-{
-	char *t;
-	int ret;
-	long e;
-	
-	ret = ares_expand_name((const unsigned char *) encoded,
-						   (const unsigned char *) abuf, alen, &t, &e);
-	if (ret == ARES_SUCCESS)
-	{
-		s.assign(t);
-		enclen = e;
-		ares_free_string(t);
-	}
-	return ret;
-}
-
-const char *LLAres::strerror(int code)
-{
-	return ares_strerror(code);
-}
-
-LLAres *gAres;
-
-LLAres *ll_init_ares()
-{
-	if (gAres == NULL)
-	{
-		gAres = new LLAres();
-	}
-	return gAres;
-}
-
-void ll_cleanup_ares()
-{
-	if (gAres != NULL)
-	{
-		delete gAres;
-		gAres = NULL;
-	}
-}
-
-LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
-						 unsigned ttl)
-	: LLRefCount(),
-	  mType(type),
-	  mName(name),
-	  mTTL(ttl)
-{
-}
-
-LLHostRecord::LLHostRecord(LLResType type, const std::string &name,
-						   unsigned ttl)
-	: LLDnsRecord(type, name, ttl)
-{
-}
-
-int LLHostRecord::parse(const char *buf, size_t len, const char *pos,
-						size_t rrlen)
-{
-	int ret;
-
-	ret = LLAres::expandName(pos, buf, len, mHost);
-	if (ret != ARES_SUCCESS)
-	{
-		goto bail;
-	}
-	
-	ret = ARES_SUCCESS;
-
-bail:
-	return ret;
-}
-
-LLCnameRecord::LLCnameRecord(const std::string &name, unsigned ttl)
-	: LLHostRecord(RES_CNAME, name, ttl)
-{
-}
-
-LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl)
-	: LLHostRecord(RES_PTR, name, ttl)
-{
-}
-
-LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name,
-			   unsigned ttl)
-	: LLDnsRecord(type, name, ttl),
-
-	  mSize(0)
-{
-}
-
-LLARecord::LLARecord(const std::string &name, unsigned ttl)
-	: LLAddrRecord(RES_A, name, ttl)
-{
-}
-
-int LLARecord::parse(const char *buf, size_t len, const char *pos,
-					 size_t rrlen)
-{
-	int ret;
-
-	if (rrlen != sizeof(mSA.sin.sin_addr.s_addr))
-	{
-		ret = ARES_EBADRESP;
-		goto bail;
-	}
-	
-	memset(&mSA, 0, sizeof(mSA));
-	memcpy(&mSA.sin.sin_addr.s_addr, pos, rrlen);
-	mSA.sin.sin_family = AF_INET6;
-	mSize = sizeof(mSA.sin);
-	
-	ret = ARES_SUCCESS;
-
-bail:
-	return ret;
-}
-
-LLAaaaRecord::LLAaaaRecord(const std::string &name, unsigned ttl)
-	: LLAddrRecord(RES_AAAA, name, ttl)
-{
-}
-
-int LLAaaaRecord::parse(const char *buf, size_t len, const char *pos,
-						size_t rrlen)
-{
-	int ret;
-
-	if (rrlen != sizeof(mSA.sin6.sin6_addr))
-	{
-		ret = ARES_EBADRESP;
-		goto bail;
-	}
-	
-	memset(&mSA, 0, sizeof(mSA));
-	memcpy(&mSA.sin6.sin6_addr.s6_addr, pos, rrlen);
-	mSA.sin6.sin6_family = AF_INET6;
-	mSize = sizeof(mSA.sin6);
-	
-	ret = ARES_SUCCESS;
-
-bail:
-	return ret;
-}
-
-LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl)
-	: LLHostRecord(RES_SRV, name, ttl),
-
-	  mPriority(0),
-	  mWeight(0),
-	  mPort(0)
-{
-}
-
-int LLSrvRecord::parse(const char *buf, size_t len, const char *pos,
-					   size_t rrlen)
-{
-	int ret;
-
-	if (rrlen < 6)
-	{
-		ret = ARES_EBADRESP;
-		goto bail;
-	}
-
-	memcpy(&mPriority, pos, 2);
-	memcpy(&mWeight, pos + 2, 2);
-	memcpy(&mPort, pos + 4, 2);
-
-	mPriority = ntohs(mPriority);
-	mWeight = ntohs(mWeight);
-	mPort = ntohs(mPort);
-
-	ret = LLHostRecord::parse(buf, len, pos + 6, rrlen - 6);
-	
-bail:
-	return ret;
-}
-
-LLNsRecord::LLNsRecord(const std::string &name, unsigned ttl)
-	: LLHostRecord(RES_NS, name, ttl)
-{
-}
-
-void LLAres::UriRewriteResponder::queryError(int code)
-{
-	std::vector<std::string> uris;
-	uris.push_back(mUri.asString());
-	rewriteResult(uris);
-}
-
-void LLAres::UriRewriteResponder::querySuccess()
-{
-	std::vector<std::string> uris;
-
-	if (mType != RES_SRV)
-	{
-		goto bail;
-	}
-		
-	for (size_t i = 0; i < mAnswers.size(); i++)
-	{
-		const LLSrvRecord *r = (const LLSrvRecord *) mAnswers[i].get();
-
-		if (r->type() == RES_SRV)
-		{
-			// Check the domain in the response to ensure that it's
-			// the same as the domain in the request, so that bad guys
-			// can't forge responses that point to their own login
-			// servers with their own certificates.
-
-			// Hard-coding the domain to check here is a bit of a
-			// hack.  Hoist it to an outer caller if anyone ever needs
-			// this functionality on other domains.
-
-			static const std::string domain(".lindenlab.com");
-			const std::string &host = r->host();
-
-			std::string::size_type s = host.find(domain) + domain.length();
-				
-			if (s != host.length() && s != host.length() - 1)
-			{
-				continue;
-			}
-			
-			LLURI uri(mUri.scheme(),
-					  mUri.userName(),
-					  mUri.password(),
-					  r->host(),
-					  mUri.defaultPort() ? r->port() : mUri.hostPort(),
-					  mUri.escapedPath(),
-					  mUri.escapedQuery());
-			uris.push_back(uri.asString());
-		}
-	}
-
-	if (!uris.empty())
-	{
-		goto done;
-	}
-
-bail:
-	uris.push_back(mUri.asString());
-
-done:
-	rewriteResult(uris);
-}
-
-void LLAres::UriRewriteResponder::rewriteResult(
-	const std::vector<std::string> &uris)
-{
-	LL_INFOS() << "LLAres::UriRewriteResponder::rewriteResult not implemented"
-			<< LL_ENDL;
-
-	for (size_t i = 0; i < uris.size(); i++)
-	{
-		LL_INFOS() << "[" << i << "] " << uris[i] << LL_ENDL;
-	}
-}
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
deleted file mode 100755
index c727363b602f913cd720a98f6d2fa28311021229..0000000000000000000000000000000000000000
--- a/indra/llmessage/llares.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/** 
- * @file llares.h
- * @author Bryan O'Sullivan
- * @date 2007-08-15
- * @brief Wrapper for asynchronous DNS lookups.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLARES_H
-#define LL_LLARES_H
-
-#ifdef LL_WINDOWS
-// ares.h is broken on windows in that it depends on types defined in ws2tcpip.h
-// we need to include them first to work around it, but the headers issue warnings
-# pragma warning(push)
-# pragma warning(disable:4996)
-# include <winsock2.h>
-# include <ws2tcpip.h>
-# pragma warning(pop)
-#endif
-
-#ifdef LL_USESYSTEMLIBS
-# include <ares.h>
-#else
-# include <ares/ares.h>
-#endif
-
-#include "llpointer.h"
-#include "llrefcount.h"
-#include "lluri.h"
-
-#include <boost/shared_ptr.hpp>
-
-class LLQueryResponder;
-class LLAresListener;
-
-/**
- * @brief Supported DNS RR types.
- */
-enum LLResType
-{
-	RES_INVALID = 0,			/**< Cookie. */
-	RES_A = 1,					/**< "A" record. IPv4 address. */
-	RES_NS = 2,					/**< "NS" record. Authoritative server. */
-	RES_CNAME = 5,				/**< "CNAME" record. Canonical name. */
-	RES_PTR = 12,				/**< "PTR" record. Domain name pointer. */
-	RES_AAAA = 28,				/**< "AAAA" record. IPv6 Address. */
-	RES_SRV = 33,				/**< "SRV" record. Server Selection. */
-	RES_MAX = 65536				/**< Sentinel; RR types are 16 bits wide. */
-};
-
-/**
- * @class LLDnsRecord
- * @brief Base class for all DNS RR types.
- */
-class LLDnsRecord : public LLRefCount
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLResType mType;
-	std::string mName;
-	unsigned mTTL;
-	
-	virtual int parse(const char *buf, size_t len, const char *pos,
-					  size_t rrlen) = 0;
-
-	LLDnsRecord(LLResType type, const std::string &name, unsigned ttl);
-	
-public:
-	/**
-	 * @brief Record name.
-	 */
-	const std::string &name() const { return mName; }
-
-	/**
-	 * @brief Time-to-live value, in seconds.
-	 */
-	unsigned ttl() const { return mTTL; }
-
-	/**
-	 * @brief RR type.
-	 */
-	LLResType type() const { return mType; }
-};
-
-/**
- * @class LLAddrRecord
- * @brief Base class for address-related RRs.
- */
-class LLAddrRecord : public LLDnsRecord
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLAddrRecord(LLResType type, const std::string &name, unsigned ttl);
-
-	union 
-	{
-		sockaddr sa;
-		sockaddr_in sin;
-		sockaddr_in6 sin6;
-	} mSA;
-
-	socklen_t mSize;
-
-public:
-	/**
-	 * @brief Generic socket address.
-	 */
-	const sockaddr &addr() const { return mSA.sa; }
-
-	/**
-	 * @brief Size of the socket structure.
-	 */
-	socklen_t size() const { return mSize; }
-};
-
-/**
- * @class LLARecord
- * @brief A RR, for IPv4 addresses.
- */
-class LLARecord : public LLAddrRecord
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLARecord(const std::string &name, unsigned ttl);
-
-	int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
-
-public:
-	/**
-	 * @brief Socket address.
-	 */
-	const sockaddr_in &addr_in() const { return mSA.sin; }
-};
-
-/**
- * @class LLAaaaRecord
- * @brief AAAA RR, for IPv6 addresses.
- */
-class LLAaaaRecord : public LLAddrRecord
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLAaaaRecord(const std::string &name, unsigned ttl);
-
-	int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
-
-public:
-	/**
-	 * @brief Socket address.
-	 */
-	const sockaddr_in6 &addr_in6() const { return mSA.sin6; }
-};
-	
-/**
- * @class LLHostRecord
- * @brief Base class for host-related RRs.
- */
-class LLHostRecord : public LLDnsRecord
-{
-protected:
-	LLHostRecord(LLResType type, const std::string &name, unsigned ttl);
-
-	int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
-
-	std::string mHost;
-
-public:
-	/**
-	 * @brief Host name.
-	 */
-	const std::string &host() const { return mHost; }
-};
-	
-/**
- * @class LLCnameRecord
- * @brief CNAME RR.
- */
-class LLCnameRecord : public LLHostRecord
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLCnameRecord(const std::string &name, unsigned ttl);
-};
-	
-/**
- * @class LLPtrRecord
- * @brief PTR RR.
- */
-class LLPtrRecord : public LLHostRecord
-{
-protected:
-	friend class LLQueryResponder;
-
-	LLPtrRecord(const std::string &name, unsigned ttl);
-};
-
-/**
- * @class LLSrvRecord
- * @brief SRV RR.
- */
-class LLSrvRecord : public LLHostRecord
-{
-protected:
-	U16 mPriority;
-	U16 mWeight;
-	U16 mPort;
-
-	int parse(const char *buf, size_t len, const char *pos, size_t rrlen);
-
-public:
-	LLSrvRecord(const std::string &name, unsigned ttl);
-
-	/**
-	 * @brief Service priority.
-	 */
-	U16 priority() const { return mPriority; }
-
-	/**
-	 * @brief Service weight.
-	 */
-	U16 weight() const { return mWeight; }
-
-	/**
-	 * @brief Port number of service.
-	 */
-	U16 port() const { return mPort; }
-
-	/**
-	 * @brief Functor for sorting SRV records by priority.
-	 */
-	struct ComparePriorityLowest
-	{
-		bool operator()(const LLSrvRecord& lhs, const LLSrvRecord& rhs)
-		{
-			return lhs.mPriority < rhs.mPriority;
-		}
-	};
-};
-	
-/**
- * @class LLNsRecord
- * @brief NS RR.
- */
-class LLNsRecord : public LLHostRecord
-{
-public:
-	LLNsRecord(const std::string &name, unsigned ttl);
-};
-
-class LLQueryResponder;
-
-/**
- * @class LLAres
- * @brief Asynchronous address resolver.
- */
-class LLAres
-{
-public:
-    /**
-	 * @class HostResponder
-	 * @brief Base class for responding to hostname lookups.
-	 * @see LLAres::getHostByName
-	 */
-	class HostResponder : public LLRefCount
-	{
-	public:
-		virtual ~HostResponder();
-
-		virtual void hostResult(const hostent *ent);
-		virtual void hostError(int code);
-	};
-
-    /**
-	 * @class NameInfoResponder
-	 * @brief Base class for responding to address lookups.
-	 * @see LLAres::getNameInfo
-	 */
-	class NameInfoResponder : public LLRefCount
-	{
-	public:
-		virtual ~NameInfoResponder();
-
-		virtual void nameInfoResult(const char *node, const char *service);
-		virtual void nameInfoError(int code);
-	};
-
-    /**
-	 * @class QueryResponder
-	 * @brief Base class for responding to custom searches.
-	 * @see LLAres::search
-	 */
-	class QueryResponder : public LLRefCount
-	{
-	public:
-		virtual ~QueryResponder();
-
-		virtual void queryResult(const char *buf, size_t len);
-		virtual void queryError(int code);
-	};
-
-	class SrvResponder;
-	class UriRewriteResponder;
-		
-	LLAres();
-
-	~LLAres();
-
-	/**
-	 * Cancel all outstanding requests.  The error methods of the
-	 * corresponding responders will be called, with ARES_ETIMEOUT.
-	 */
-	void cancel();
-	
-	/**
-	 * Look up the address of a host.
-	 *
-	 * @param name name of host to look up
-	 * @param resp responder to call with result
-	 * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
-	 */
-	void getHostByName(const std::string &name, HostResponder *resp,
-					   int family = AF_INET) {
-		getHostByName(name.c_str(), resp, family);
-	}
-
-	/**
-	 * Look up the address of a host.
-	 *
-	 * @param name name of host to look up
-	 * @param resp responder to call with result
-	 * @param family AF_INET for IPv4 addresses, AF_INET6 for IPv6
-	 */
-	void getHostByName(const char *name, HostResponder *resp,
-					   int family = PF_INET);
-
-	/**
-	 * Look up the name associated with a socket address.
-	 *
-	 * @param sa socket address to look up
-	 * @param salen size of socket address
-	 * @param flags flags to use
-	 * @param resp responder to call with result
-	 */
-	void getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
-					 NameInfoResponder *resp);
-
-	/**
-	 * Look up SRV (service location) records for a service name.
-	 *
-	 * @param name service name (e.g. "_https._tcp.login.agni.lindenlab.com")
-	 * @param resp responder to call with result
-	 */
-	void getSrvRecords(const std::string &name, SrvResponder *resp);
-
-	/**
-	 * Rewrite a URI, using SRV (service location) records for its
-	 * protocol if available.  If no SRV records are published, the
-	 * existing URI is handed to the responder.
-	 *
-	 * @param uri URI to rewrite
-	 * @param resp responder to call with result
-	 */
-	void rewriteURI(const std::string &uri,
-					UriRewriteResponder *resp);
-
-	/**
-	 * Start a custom search.
-	 *
-	 * @param query query to make
-	 * @param type type of query to perform
-	 * @param resp responder to call with result
-	 */
-	void search(const std::string &query, LLResType type,
-				QueryResponder *resp);
-
-	/**
-	 * Process any outstanding queries.  This method takes an optional
-	 * timeout parameter (specified in microseconds).  If provided, it
-	 * will block the calling thread for that length of time to await
-	 * possible responses. A timeout of zero will return immediately
-	 * if there are no responses or timeouts to process.
-	 *
-	 * @param timeoutUsecs number of microseconds to block before timing out
-	 * @return whether any responses were processed
-	 */
-	bool process(U64 timeoutUsecs = 0);
-
-	/**
-	 * Process all outstanding queries, blocking the calling thread
-	 * until all have either been responded to or timed out.
-	 *
-	 * @return whether any responses were processed
-	 */
-	bool processAll();
-	
-	/**
-	 * Expand a DNS-encoded compressed string into a normal string.
-	 *
-	 * @param encoded the encoded name (null-terminated)
-	 * @param abuf the response buffer in which the string is embedded
-	 * @param alen the length of the response buffer
-	 * @param s the string into which to place the result
-	 * @return ARES_SUCCESS on success, otherwise an error indicator
-	 */
-	static int expandName(const char *encoded, const char *abuf, size_t alen,
-						  std::string &s) {
-		size_t ignore;
-		return expandName(encoded, abuf, alen, s, ignore);
-	}
-	
-	static int expandName(const char *encoded, const char *abuf, size_t alen,
-						  std::string &s, size_t &enclen);
-
-	/**
-	 * Return a string describing an error code.
-	 */
-	static const char *strerror(int code);
-
-	bool isInitialized(void) { return mInitSuccess; }
-
-protected:
-	ares_channel chan_;
-	bool mInitSuccess;
-    // boost::scoped_ptr would actually fit the requirement better, but it
-    // can't handle incomplete types as boost::shared_ptr can.
-    boost::shared_ptr<LLAresListener> mListener;
-};
-	
-/**
- * An ordered collection of DNS resource records.
- */
-typedef std::vector<LLPointer<LLDnsRecord> > dns_rrs_t;
-
-/**
- * @class LLQueryResponder
- * @brief Base class for friendly handling of DNS query responses.
- *
- * This class parses a DNS response and represents it in a friendly
- * manner.
- *
- * @see LLDnsRecord
- * @see LLARecord
- * @see LLNsRecord
- * @see LLCnameRecord
- * @see LLPtrRecord
- * @see LLAaaaRecord
- * @see LLSrvRecord
- */
-class LLQueryResponder : public LLAres::QueryResponder
-{
-protected:
-	int mResult;
-	std::string mQuery;
-	LLResType mType;
-	
-	dns_rrs_t mAnswers;
-	dns_rrs_t mAuthorities;
-	dns_rrs_t mAdditional;
-
-	/**
-	 * Parse a single RR.
-	 */
-	int parseRR(const char *buf, size_t len, const char *&pos,
-				LLPointer<LLDnsRecord> &r);
-	/**
-	 * Parse one section of a response.
-	 */
-	int parseSection(const char *buf, size_t len,
-					 size_t count, const char *& pos, dns_rrs_t &rrs);
-
-	void queryResult(const char *buf, size_t len);
-	virtual void querySuccess();
-
-public:
-	LLQueryResponder();
-
-	/**
-	 * Indicate whether the response could be parsed successfully.
-	 */
-	bool valid() const { return mResult == ARES_SUCCESS; }
-
-	/**
-	 * The more detailed result of parsing the response.
-	 */
-	int result() const { return mResult; }
-	
-	/**
-	 * Return the query embedded in the response.
-	 */
-	const std::string &query() const { return mQuery; }
-
-	/**
-	 * Return the contents of the "answers" section of the response.
-	 */
-	const dns_rrs_t &answers() const { return mAnswers; }
-
-	/**
-	 * Return the contents of the "authorities" section of the
-	 * response.
-	 */
-	const dns_rrs_t &authorities() const { return mAuthorities; }
-
-	/**
-	 * Return the contents of the "additional records" section of the
-	 * response.
-	 */
-	const dns_rrs_t &additional() const { return mAdditional; }
-};
-
-/**
- * @class LLAres::SrvResponder
- * @brief Class for handling SRV query responses.
- */
-class LLAres::SrvResponder : public LLQueryResponder
-{
-public:
-	friend void LLAres::getSrvRecords(const std::string &name,
-									  SrvResponder *resp);
-	void querySuccess();
-	void queryError(int code);
-
-	virtual void srvResult(const dns_rrs_t &ents);
-	virtual void srvError(int code);
-};
-
-/**
- * @class LLAres::UriRewriteResponder
- * @brief Class for handling URI rewrites based on SRV records.
- */
-class LLAres::UriRewriteResponder : public LLQueryResponder
-{
-protected:
-	LLURI mUri;
-
-public:
-	friend void LLAres::rewriteURI(const std::string &uri,
-								   UriRewriteResponder *resp);
-	void querySuccess();
-	void queryError(int code);
-
-	virtual void rewriteResult(const std::vector<std::string> &uris);
-};
-	
-/**
- * Singleton responder.
- */
-extern LLAres *gAres;
-
-/**
- * Set up the singleton responder.  It's safe to call this more than
- * once from within a single thread, but this function is not
- * thread safe.
- */
-extern LLAres *ll_init_ares();
-extern void ll_cleanup_ares();
-
-#endif // LL_LLARES_H
diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp
deleted file mode 100755
index 3d65906b980ba80d7394f4ef4e6f496c8890e012..0000000000000000000000000000000000000000
--- a/indra/llmessage/llareslistener.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * @file   llareslistener.cpp
- * @author Nat Goodspeed
- * @date   2009-03-18
- * @brief  Implementation for llareslistener.
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llareslistener.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-#include "llares.h"
-#include "llerror.h"
-#include "llevents.h"
-#include "llsdutil.h"
-
-LLAresListener::LLAresListener(LLAres* llares):
-    LLEventAPI("LLAres",
-               "LLAres listener to request DNS operations"),
-    mAres(llares)
-{
-    // add() every method we want to be able to invoke via this event API.
-    // Optional last parameter validates expected LLSD request structure.
-    add("rewriteURI",
-        "Given [\"uri\"], return on [\"reply\"] an array of alternative URIs.\n"
-        "On failure, returns an array containing only the original URI, so\n"
-        "failure case can be processed like success case.",
-        &LLAresListener::rewriteURI,
-        LLSD().with("uri", LLSD()).with("reply", LLSD()));
-}
-
-/// This UriRewriteResponder subclass packages returned URIs as an LLSD
-/// array to send back to the requester.
-class UriRewriteResponder: public LLAres::UriRewriteResponder
-{
-public:
-    /**
-     * Specify the request, containing the event pump name on which to send
-     * the reply.
-     */
-    UriRewriteResponder(const LLSD& request):
-        mReqID(request),
-        mPumpName(request["reply"])
-    {}
-
-    /// Called by base class with results. This is called in both the
-    /// success and error cases. On error, the calling logic passes the
-    /// original URI.
-    virtual void rewriteResult(const std::vector<std::string>& uris)
-    {
-        LLSD result;
-        for (std::vector<std::string>::const_iterator ui(uris.begin()), uend(uris.end());
-             ui != uend; ++ui)
-        {
-            result.append(*ui);
-        }
-        // This call knows enough to avoid trying to insert a map key into an
-        // LLSD array. It's there so that if, for any reason, we ever decide
-        // to change the response from array to map, it will Just Start Working.
-        mReqID.stamp(result);
-        LLEventPumps::instance().obtain(mPumpName).post(result);
-    }
-
-private:
-    LLReqID mReqID;
-    const std::string mPumpName;
-};
-
-void LLAresListener::rewriteURI(const LLSD& data)
-{
-	if (mAres)
-	{
-		mAres->rewriteURI(data["uri"], new UriRewriteResponder(data));
-	}
-	else
-	{
-		LL_INFOS() << "LLAresListener::rewriteURI requested without Ares present. Ignoring: " << data << LL_ENDL;
-	}
-}
diff --git a/indra/llmessage/llareslistener.h b/indra/llmessage/llareslistener.h
deleted file mode 100755
index 780dcdd9c55806fb9e0e1e307573ac3cab9b201f..0000000000000000000000000000000000000000
--- a/indra/llmessage/llareslistener.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * @file   llareslistener.h
- * @author Nat Goodspeed
- * @date   2009-03-18
- * @brief  LLEventPump API for LLAres. This header doesn't actually define the
- *         API; the API is defined by the pump name on which this class
- *         listens, and by the expected content of LLSD it receives.
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLARESLISTENER_H)
-#define LL_LLARESLISTENER_H
-
-#include "lleventapi.h"
-
-class LLAres;
-class LLSD;
-
-/// Listen on an LLEventPump with specified name for LLAres request events.
-class LLAresListener: public LLEventAPI
-{
-public:
-    /// Bind the LLAres instance to use (e.g. gAres)
-    LLAresListener(LLAres* llares);
-
-private:
-    /// command["op"] == "rewriteURI" 
-    void rewriteURI(const LLSD& data);
-
-    LLAres* mAres;
-};
-
-#endif /* ! defined(LL_LLARESLISTENER_H) */
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 61663e1982a2176c6fdf232356f065a55762dfd4..0d8aaf2269b0ce0773909a8c0503676a4d53ed91 100755
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -290,7 +290,7 @@ LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS
 LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
 							   LLVFS *vfs, LLVFS *static_vfs)
 {
-	_init(msg, xfer, vfs, static_vfs, LLHost::invalid);
+	_init(msg, xfer, vfs, static_vfs, LLHost());
 }
 
 
@@ -1609,3 +1609,4 @@ void	LLAssetStorage::markAssetToxic( const LLUUID& uuid )
 	}
 }
 
+
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 1bb4acea9ea1608c9800e61475c7bc3691210fb1..c3d31ba84c6c9d0f6d97fcce63b1cde9989a2505 100755
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -27,7 +27,6 @@
 
 #ifndef LL_LLASSETSTORAGE_H
 #define LL_LLASSETSTORAGE_H
-
 #include <string>
 
 #include "lluuid.h"
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 549708097ab45b6ce27f25eff9762670adf63fa3..61f18ed63e1191795f22b5a8495bb1937e71b5f0 100755
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -30,12 +30,20 @@
 
 #include "llcachename.h"		// we wrap this system
 #include "llframetimer.h"
-#include "llhttpclient.h"
 #include "llsd.h"
 #include "llsdserialize.h"
-
+#include "httpresponse.h"
+#include "llhttpsdhandler.h"
 #include <boost/tokenizer.hpp>
 
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+
 #include <map>
 #include <set>
 
@@ -90,6 +98,12 @@ namespace LLAvatarNameCache
 	// Time-to-live for a temp cache entry.
 	const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
 
+    LLCore::HttpRequest::ptr_t		sHttpRequest;
+    LLCore::HttpHeaders::ptr_t		sHttpHeaders;
+    LLCore::HttpOptions::ptr_t		sHttpOptions;
+    LLCore::HttpRequest::policy_t	sHttpPolicy;
+    LLCore::HttpRequest::priority_t	sHttpPriority;
+
 	//-----------------------------------------------------------------------
 	// Internal methods
 	//-----------------------------------------------------------------------
@@ -121,7 +135,12 @@ namespace LLAvatarNameCache
 	// Erase expired names from cache
 	void eraseUnrefreshed();
 
-	bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+    bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+
+    // This is a coroutine.
+    void requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds);
+
+    void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult);
 }
 
 /* Sample response:
@@ -163,94 +182,117 @@ namespace LLAvatarNameCache
 </llsd>
 */
 
-class LLAvatarNameResponder : public LLHTTPClient::Responder
+// Coroutine for sending and processing avatar name cache requests.  
+// Do not call directly.  See documentation in lleventcoro.h and llcoro.h for
+// further explanation.
+void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds)
 {
-	LOG_CLASS(LLAvatarNameResponder);
-private:
-	// need to store agent ids that are part of this request in case of
-	// an error, so we can flag them as unavailable
-	std::vector<LLUUID> mAgentIDs;
-
-public:
-	LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
-	:	mAgentIDs(agent_ids)
-	{ }
-	
-protected:
-	/*virtual*/ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		// Pull expiration out of headers if available
-		F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
-		F64 now = LLFrameTimer::getTotalSeconds();
+    LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName()
+        << " with url '" << url << "', requesting " << agentIds.size() << " Agent Ids" << LL_ENDL;
 
-		const LLSD& agents = content["agents"];
-		LLSD::array_const_iterator it = agents.beginArray();
-		for ( ; it != agents.endArray(); ++it)
-		{
-			const LLSD& row = *it;
-			LLUUID agent_id = row["id"].asUUID();
+    try
+    {
+        bool success = true;
 
-			LLAvatarName av_name;
-			av_name.fromLLSD(row);
+        LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("NameCache", LLAvatarNameCache::sHttpPolicy);
+        LLSD results = httpAdapter.getAndSuspend(sHttpRequest, url);
+        LLSD httpResults;
 
-			// Use expiration time from header
-			av_name.mExpires = expires;
+        LL_DEBUGS() << results << LL_ENDL;
 
-			LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
-			av_name.dump();
-			
-			// cache it and fire signals
-			LLAvatarNameCache::processName(agent_id, av_name);
-		}
+        if (!results.isMap())
+        {
+            LL_WARNS("AvNameCache") << " Invalid result returned from LLCoreHttpUtil::HttpCoroHandler." << LL_ENDL;
+            success = false;
+        }
+        else
+        {
+            httpResults = results["http_result"];
+            success = httpResults["success"].asBoolean();
+            if (!success)
+            {
+                LL_WARNS("AvNameCache") << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+                    << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
+            }
+        }
 
-		// Same logic as error response case
-		const LLSD& unresolved_agents = content["bad_ids"];
-		S32  num_unresolved = unresolved_agents.size();
-		if (num_unresolved > 0)
-		{
-            LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
-                                    << "expires in " << expires - now << " seconds"
-                                    << LL_ENDL;
-			it = unresolved_agents.beginArray();
-			for ( ; it != unresolved_agents.endArray(); ++it)
-			{
-				const LLUUID& agent_id = *it;
+        if (!success)
+        {   // on any sort of failure add dummy records for any agent IDs 
+            // in this request that we do not have cached already
+            std::vector<LLUUID>::const_iterator it = agentIds.begin();
+            for ( ; it != agentIds.end(); ++it)
+            {
+                const LLUUID& agent_id = *it;
+                LLAvatarNameCache::handleAgentError(agent_id);
+            }
+            return;
+        }
 
-				LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
-                                        << "failed id " << agent_id
-                                        << LL_ENDL;
+        LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
 
-                LLAvatarNameCache::handleAgentError(agent_id);
-			}
-		}
-        LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result " 
-                                 << LLAvatarNameCache::sCache.size() << " cached names"
-                                 << LL_ENDL;
     }
+    catch (std::exception e)
+    {
+        LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
+    }
+    catch (...)
+    {
+        LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+    }
+}
 
-	/*virtual*/ void httpFailure()
-	{
-		// If there's an error, it might be caused by PeopleApi,
-		// or when loading textures on startup and using a very slow 
-		// network, this query may time out.
-		// What we should do depends on whether or not we have a cached name
-		LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
-
-		// Add dummy records for any agent IDs in this request that we do not have cached already
-		std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
-		for ( ; it != mAgentIDs.end(); ++it)
-		{
-			const LLUUID& agent_id = *it;
-			LLAvatarNameCache::handleAgentError(agent_id);
-		}
-	}
-};
+void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult)
+{
+
+    LLSD headers = httpResult["headers"];
+    // Pull expiration out of headers if available
+    F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(headers);
+    F64 now = LLFrameTimer::getTotalSeconds();
+
+    const LLSD& agents = data["agents"];
+    LLSD::array_const_iterator it = agents.beginArray();
+    for (; it != agents.endArray(); ++it)
+    {
+        const LLSD& row = *it;
+        LLUUID agent_id = row["id"].asUUID();
+
+        LLAvatarName av_name;
+        av_name.fromLLSD(row);
+
+        // Use expiration time from header
+        av_name.mExpires = expires;
+
+        LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
+        av_name.dump();
+
+        // cache it and fire signals
+        LLAvatarNameCache::processName(agent_id, av_name);
+    }
+
+    // Same logic as error response case
+    const LLSD& unresolved_agents = data["bad_ids"];
+    S32  num_unresolved = unresolved_agents.size();
+    if (num_unresolved > 0)
+    {
+        LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result " << num_unresolved << " unresolved ids; "
+            << "expires in " << expires - now << " seconds"
+            << LL_ENDL;
+        it = unresolved_agents.beginArray();
+        for (; it != unresolved_agents.endArray(); ++it)
+        {
+            const LLUUID& agent_id = *it;
+
+            LL_WARNS("AvNameCache") << "LLAvatarNameResponder::result "
+                << "failed id " << agent_id
+                << LL_ENDL;
+
+            LLAvatarNameCache::handleAgentError(agent_id);
+        }
+    }
+    LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
+        << LLAvatarNameCache::sCache.size() << " cached names"
+        << LL_ENDL;
+}
 
 // Provide some fallback for agents that return errors
 void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
@@ -353,10 +395,15 @@ void LLAvatarNameCache::requestNamesViaCapability()
 		}
 	}
 
-	if (!url.empty())
-	{
-		LL_INFOS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability getting " << ids << " ids" << LL_ENDL;
-		LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+    if (!url.empty())
+    {
+        LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested " << ids << " ids" << LL_ENDL;
+
+        std::string coroname = 
+            LLCoros::instance().launch("LLAvatarNameCache::requestAvatarNameCache_",
+            boost::bind(&LLAvatarNameCache::requestAvatarNameCache_, url, agent_ids));
+        LL_DEBUGS("AvNameCache") << coroname << " with  url '" << url << "', agent_ids.size()=" << agent_ids.size() << LL_ENDL;
+
 	}
 }
 
@@ -419,11 +466,20 @@ void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI)
 {
 	sRunning = running;
 	sUsePeopleAPI = usePeopleAPI;
+
+    sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+    sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
+    sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
+    sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+    sHttpPriority = 0;
 }
 
 void LLAvatarNameCache::cleanupClass()
 {
-	sCache.clear();
+    sHttpRequest.reset();
+    sHttpHeaders.reset();
+    sHttpOptions.reset();
+    sCache.clear();
 }
 
 bool LLAvatarNameCache::importFile(std::istream& istr)
@@ -698,6 +754,50 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
 	sCache[agent_id] = av_name;
 }
 
+#if 0
+F64 LLAvatarNameCache::nameExpirationFromHeaders(LLCore::HttpHeaders *headers)
+{
+    F64 expires = 0.0;
+    if (expirationFromCacheControl(headers, &expires))
+    {
+        return expires;
+    }
+    else
+    {
+        // With no expiration info, default to an hour
+        const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
+        F64 now = LLFrameTimer::getTotalSeconds();
+        return now + DEFAULT_EXPIRES;
+    }
+}
+
+bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers, F64 *expires)
+{
+    bool fromCacheControl = false;
+    F64 now = LLFrameTimer::getTotalSeconds();
+
+    // Allow the header to override the default
+    const std::string *cache_control;
+    
+    cache_control = headers->find(HTTP_IN_HEADER_CACHE_CONTROL);
+
+    if (cache_control && !cache_control->empty())
+    {
+        S32 max_age = 0;
+        if (max_age_from_cache_control(*cache_control, &max_age))
+        {
+            *expires = now + (F64)max_age;
+            fromCacheControl = true;
+        }
+    }
+    LL_DEBUGS("AvNameCache")
+        << ( fromCacheControl ? "expires based on cache control " : "default expiration " )
+        << "in " << *expires - now << " seconds"
+        << LL_ENDL;
+
+    return fromCacheControl;
+}
+#else
 F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
 {
 	F64 expires = 0.0;
@@ -742,7 +842,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *exp
 	
 	return fromCacheControl;
 }
-
+#endif
 
 void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb) 
 { 
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 5a10053a69288180032d7a12d8d8de3ecaf855c9..bd2715e9567607d7f15d57124c63190dea6d5513 100755
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -29,7 +29,6 @@
 #define LLAVATARNAMECACHE_H
 
 #include "llavatarname.h"	// for convenience
-
 #include <boost/signals2.hpp>
 
 class LLSD;
@@ -49,7 +48,7 @@ namespace LLAvatarNameCache
 	bool importFile(std::istream& istr);
 	void exportFile(std::ostream& ostr);
 
-	// On the viewer, usually a simulator capabilitity.
+	// On the viewer, usually a simulator capabilities.
 	// If empty, name cache will fall back to using legacy name lookup system.
 	void setNameLookupURL(const std::string& name_lookup_url);
 
@@ -90,7 +89,7 @@ namespace LLAvatarNameCache
 
 	// Compute name expiration time from HTTP Cache-Control header,
 	// or return default value, in seconds from epoch.
-	F64 nameExpirationFromHeaders(const LLSD& headers);
+    F64 nameExpirationFromHeaders(const LLSD& headers);
 
 	void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
 }
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index daf3e0b4dede469b218ed9fc8de7dda7bc135eee..66bd85f4e6aceae6c0af0864ee616aa94aa746a1 100755
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -259,7 +259,7 @@ LLCacheName::~LLCacheName()
 }
 
 LLCacheName::Impl::Impl(LLMessageSystem* msg)
-	: mMsg(msg), mUpstreamHost(LLHost::invalid)
+	: mMsg(msg), mUpstreamHost(LLHost())
 {
 	mMsg->setHandlerFuncFast(
 		_PREHASH_UUIDNameRequest, handleUUIDNameRequest, (void**)this);
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0fe1ab01b14d718b65c104baccb63dbd2cf6bb0
--- /dev/null
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -0,0 +1,405 @@
+/**
+* @file LLCoprocedurePool.cpp
+* @author Rider Linden
+* @brief Singleton class for managing asset uploads to the sim.
+*
+* $LicenseInfo:firstyear=2015&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2015, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h" 
+#include "llcoproceduremanager.h"
+#include <boost/assign.hpp>
+
+//=========================================================================
+// Map of pool sizes for known pools
+// *TODO$: When C++11 this can be initialized here as follows:
+// = {{"AIS", 25}, {"Upload", 1}}
+static std::map<std::string, U32> DefaultPoolSizes = 
+    boost::assign::map_list_of
+        (std::string("Upload"),  1)
+        (std::string("AIS"),    25);
+
+#define DEFAULT_POOL_SIZE 5
+
+//=========================================================================
+class LLCoprocedurePool: private boost::noncopyable
+{
+public:
+    typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t;
+
+    LLCoprocedurePool(const std::string &name, size_t size);
+    virtual ~LLCoprocedurePool();
+
+    /// Places the coprocedure on the queue for processing. 
+    /// 
+    /// @param name Is used for debugging and should identify this coroutine.
+    /// @param proc Is a bound function to be executed 
+    /// 
+    /// @return This method returns a UUID that can be used later to cancel execution.
+    LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc);
+
+    /// Cancel a coprocedure. If the coprocedure is already being actively executed 
+    /// this method calls cancelSuspendedOperation() on the associated HttpAdapter
+    /// If it has not yet been dequeued it is simply removed from the queue.
+    bool cancelCoprocedure(const LLUUID &id);
+
+    /// Requests a shutdown of the upload manager. Passing 'true' will perform 
+    /// an immediate kill on the upload coroutine.
+    void shutdown(bool hardShutdown = false);
+
+    /// Returns the number of coprocedures in the queue awaiting processing.
+    ///
+    inline size_t countPending() const
+    {
+        return mPendingCoprocs.size();
+    }
+
+    /// Returns the number of coprocedures actively being processed.
+    ///
+    inline size_t countActive() const
+    {
+        return mActiveCoprocs.size();
+    }
+
+    /// Returns the total number of coprocedures either queued or in active processing.
+    ///
+    inline size_t count() const
+    {
+        return countPending() + countActive();
+    }
+
+private:
+    struct QueuedCoproc
+    {
+        typedef boost::shared_ptr<QueuedCoproc> ptr_t;
+
+        QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) :
+            mName(name),
+            mId(id),
+            mProc(proc)
+        {}
+
+        std::string mName;
+        LLUUID mId;
+        CoProcedure_t mProc;
+    };
+
+    // we use a deque here rather than std::queue since we want to be able to 
+    // iterate through the queue and potentially erase an entry from the middle.
+    typedef std::deque<QueuedCoproc::ptr_t>  CoprocQueue_t;
+    typedef std::map<LLUUID, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> ActiveCoproc_t;
+
+    std::string     mPoolName;
+    size_t          mPoolSize;
+    CoprocQueue_t   mPendingCoprocs;
+    ActiveCoproc_t  mActiveCoprocs;
+    bool            mShutdown;
+    LLEventStream   mWakeupTrigger;
+
+    typedef std::map<std::string, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> CoroAdapterMap_t;
+    LLCore::HttpRequest::policy_t mHTTPPolicy;
+
+    CoroAdapterMap_t mCoroMapping;
+
+    void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter);
+
+};
+
+//=========================================================================
+LLCoprocedureManager::LLCoprocedureManager()
+{
+}
+
+LLCoprocedureManager::~LLCoprocedureManager()
+{
+
+}
+
+LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName)
+{
+    // Attempt to look up a pool size in the configuration.  If found use that
+    std::string keyName = "PoolSize" + poolName;
+    int size = 0;
+
+    if (poolName.empty())
+        LL_ERRS("CoprocedureManager") << "Poolname must not be empty" << LL_ENDL;
+
+    if (mPropertyQueryFn && !mPropertyQueryFn.empty())
+    {
+        size = mPropertyQueryFn(keyName);
+    }
+
+    if (size == 0)
+    {   // if not found grab the know default... if there is no known 
+        // default use a reasonable number like 5.
+        std::map<std::string, U32>::iterator it = DefaultPoolSizes.find(poolName);
+        if (it == DefaultPoolSizes.end())
+            size = DEFAULT_POOL_SIZE;
+        else
+            size = (*it).second;
+
+        if (mPropertyDefineFn && !mPropertyDefineFn.empty())
+            mPropertyDefineFn(keyName, size, "Coroutine Pool size for " + poolName);
+        LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL;
+    }
+
+    poolPtr_t pool(new LLCoprocedurePool(poolName, size));
+    mPoolMap.insert(poolMap_t::value_type(poolName, pool));
+
+    if (!pool)
+        LL_ERRS("CoprocedureManager") << "Unable to create pool named \"" << poolName << "\" FATAL!" << LL_ENDL;
+    return pool;
+}
+
+//-------------------------------------------------------------------------
+LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc)
+{
+    // Attempt to find the pool and enqueue the procedure.  If the pool does 
+    // not exist, create it.
+    poolPtr_t targetPool;
+    poolMap_t::iterator it = mPoolMap.find(pool);
+
+    if (it == mPoolMap.end())
+    {
+        targetPool = initializePool(pool);
+    }
+    else
+    {
+        targetPool = (*it).second;
+    }
+
+    return targetPool->enqueueCoprocedure(name, proc);
+}
+
+void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id)
+{
+    for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it)
+    {
+        if ((*it).second->cancelCoprocedure(id))
+            return;
+    }
+    LL_INFOS() << "Coprocedure not found." << LL_ENDL;
+}
+
+void LLCoprocedureManager::shutdown(bool hardShutdown)
+{
+    for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it)
+    {
+        (*it).second->shutdown(hardShutdown);
+    }
+    mPoolMap.clear();
+}
+
+void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn)
+{
+    mPropertyQueryFn = queryfn;
+    mPropertyDefineFn = updatefn;
+}
+
+//-------------------------------------------------------------------------
+size_t LLCoprocedureManager::countPending() const
+{
+    size_t count = 0;
+    for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it)
+    {
+        count += (*it).second->countPending();
+    }
+    return count;
+}
+
+size_t LLCoprocedureManager::countPending(const std::string &pool) const
+{
+    poolMap_t::const_iterator it = mPoolMap.find(pool);
+
+    if (it == mPoolMap.end())
+        return 0;
+    return (*it).second->countPending();
+}
+
+size_t LLCoprocedureManager::countActive() const
+{
+    size_t count = 0;
+    for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it)
+    {
+        count += (*it).second->countActive();
+    }
+    return count;
+}
+
+size_t LLCoprocedureManager::countActive(const std::string &pool) const
+{
+    poolMap_t::const_iterator it = mPoolMap.find(pool);
+
+    if (it == mPoolMap.end())
+        return 0;
+    return (*it).second->countActive();
+}
+
+size_t LLCoprocedureManager::count() const
+{
+    size_t count = 0;
+    for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it)
+    {
+        count += (*it).second->count();
+    }
+    return count;
+}
+
+size_t LLCoprocedureManager::count(const std::string &pool) const
+{
+    poolMap_t::const_iterator it = mPoolMap.find(pool);
+
+    if (it == mPoolMap.end())
+        return 0;
+    return (*it).second->count();
+}
+
+//=========================================================================
+LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
+    mPoolName(poolName),
+    mPoolSize(size),
+    mPendingCoprocs(),
+    mShutdown(false),
+    mWakeupTrigger("CoprocedurePool" + poolName, true),
+    mCoroMapping(),
+    mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID)
+{
+    for (size_t count = 0; count < mPoolSize; ++count)
+    {
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy));
+
+        std::string pooledCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro",
+            boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter));
+
+        mCoroMapping.insert(CoroAdapterMap_t::value_type(pooledCoro, httpAdapter));
+    }
+
+    LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL;
+
+    mWakeupTrigger.post(LLSD());
+}
+
+LLCoprocedurePool::~LLCoprocedurePool() 
+{
+    shutdown();
+}
+
+//-------------------------------------------------------------------------
+void LLCoprocedurePool::shutdown(bool hardShutdown)
+{
+    CoroAdapterMap_t::iterator it;
+
+    for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it)
+    {
+        if (hardShutdown)
+        {
+            LLCoros::instance().kill((*it).first);
+        }
+        if ((*it).second)
+        {
+            (*it).second->cancelSuspendedOperation();
+        }
+    }
+
+    mShutdown = true;
+    mCoroMapping.clear();
+    mPendingCoprocs.clear();
+}
+
+//-------------------------------------------------------------------------
+LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc)
+{
+    LLUUID id(LLUUID::generateNewID());
+
+    mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc)));
+    LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+
+    mWakeupTrigger.post(LLSD());
+
+    return id;
+}
+
+bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id)
+{
+    // first check the active coroutines.  If there, remove it and return.
+    ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id);
+    if (itActive != mActiveCoprocs.end())
+    {
+        LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+        (*itActive).second->cancelSuspendedOperation();
+        mActiveCoprocs.erase(itActive);
+        return true;
+    }
+
+    for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it)
+    {
+        if ((*it)->mId == id)
+        {
+            LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+            mPendingCoprocs.erase(it);
+            return true;
+        }
+    }
+
+    LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found in pool \"" << mPoolName << "\"" << LL_ENDL;
+    return false;
+}
+
+//-------------------------------------------------------------------------
+void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    while (!mShutdown)
+    {
+        llcoro::suspendUntilEventOn(mWakeupTrigger);
+        if (mShutdown)
+            break;
+        
+        while (!mPendingCoprocs.empty())
+        {
+            QueuedCoproc::ptr_t coproc = mPendingCoprocs.front();
+            mPendingCoprocs.pop_front();
+            ActiveCoproc_t::iterator itActive = mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)).first;
+
+            LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+
+            try
+            {
+                coproc->mProc(httpAdapter, coproc->mId);
+            }
+            catch (std::exception &e)
+            {
+                LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() <<
+                    " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL;
+            }
+            catch (...)
+            {
+                LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+            }
+
+            LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
+
+            mActiveCoprocs.erase(itActive);
+        }
+    }
+}
diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h
new file mode 100644
index 0000000000000000000000000000000000000000..497367b80cdc5713415a1cbd5f27320fcde950a8
--- /dev/null
+++ b/indra/llmessage/llcoproceduremanager.h
@@ -0,0 +1,98 @@
+/**
+* @file llcoproceduremanager.h
+* @author Rider Linden
+* @brief Singleton class for managing asset uploads to the sim.
+*
+* $LicenseInfo:firstyear=2015&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2015, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_COPROCEDURE_MANAGER_H
+#define LL_COPROCEDURE_MANAGER_H
+
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llcorehttputil.h"
+#include "lluuid.h"
+
+class LLCoprocedurePool;
+
+class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager >
+{
+    friend class LLSingleton < LLCoprocedureManager > ;
+
+public:
+    typedef boost::function<U32(const std::string &)> SettingQuery_t;
+    typedef boost::function<void(const std::string &, U32, const std::string &)> SettingUpdate_t;
+
+    typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t;
+
+    LLCoprocedureManager();
+    virtual ~LLCoprocedureManager();
+
+    /// Places the coprocedure on the queue for processing. 
+    /// 
+    /// @param name Is used for debugging and should identify this coroutine.
+    /// @param proc Is a bound function to be executed 
+    /// 
+    /// @return This method returns a UUID that can be used later to cancel execution.
+    LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc);
+
+    /// Cancel a coprocedure. If the coprocedure is already being actively executed 
+    /// this method calls cancelYieldingOperation() on the associated HttpAdapter
+    /// If it has not yet been dequeued it is simply removed from the queue.
+    void cancelCoprocedure(const LLUUID &id);
+
+    /// Requests a shutdown of the upload manager. Passing 'true' will perform 
+    /// an immediate kill on the upload coroutine.
+    void shutdown(bool hardShutdown = false);
+
+    void setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn);
+
+    /// Returns the number of coprocedures in the queue awaiting processing.
+    ///
+    size_t countPending() const;
+    size_t countPending(const std::string &pool) const;
+
+    /// Returns the number of coprocedures actively being processed.
+    ///
+    size_t countActive() const;
+    size_t countActive(const std::string &pool) const;
+
+    /// Returns the total number of coprocedures either queued or in active processing.
+    ///
+    size_t count() const;
+    size_t count(const std::string &pool) const;
+
+private:
+
+    typedef boost::shared_ptr<LLCoprocedurePool> poolPtr_t;
+    typedef std::map<std::string, poolPtr_t> poolMap_t;
+
+    poolMap_t mPoolMap;
+
+    poolPtr_t initializePool(const std::string &poolName);
+
+    SettingQuery_t mPropertyQueryFn;
+    SettingUpdate_t mPropertyDefineFn;
+};
+
+#endif
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index ee80b0fd949c572ac462813af37af9003e4ae887..d964ff71006a28794a130a9338df42703097e71f 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -28,10 +28,18 @@
 #include "linden_common.h"
 
 #include <sstream>
-
+#include <algorithm>
+#include <iterator>
 #include "llcorehttputil.h"
+#include "llhttpconstants.h"
+#include "llsd.h"
+#include "llsdjson.h"
 #include "llsdserialize.h"
+#include "reader.h" // JSON
+#include "writer.h" // JSON
+#include "llvfile.h"
 
+#include "message.h" // for getting the port
 
 using namespace LLCore;
 
@@ -39,101 +47,1178 @@ using namespace LLCore;
 namespace LLCoreHttpUtil
 {
 
+const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
+
+
+void logMessageSuccess(std::string logAuth, std::string url, std::string message)
+{
+    LL_INFOS() << logAuth << " Success '" << message << "' for " << url << LL_ENDL;
+}
+
+void logMessageFail(std::string logAuth, std::string url, std::string message)
+{
+    LL_WARNS() << logAuth << " Failure '" << message << "' for " << url << LL_ENDL;
+}
+
+//=========================================================================
+/// The HttpRequestPumper is a utility class. When constructed it will poll the 
+/// supplied HttpRequest once per frame until it is destroyed.
+/// 
+class HttpRequestPumper
+{
+public:
+    HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request);
+    ~HttpRequestPumper();
+
+private:
+    bool                       pollRequest(const LLSD&);
+
+    LLTempBoundListener        mBoundListener;
+    LLCore::HttpRequest::ptr_t mHttpRequest;
+};
+
+
+//=========================================================================
 // *TODO:  Currently converts only from XML content.  A mode
 // to convert using fromBinary() might be useful as well.  Mesh
 // headers could use it.
 bool responseToLLSD(HttpResponse * response, bool log, LLSD & out_llsd)
 {
-	// Convert response to LLSD
-	BufferArray * body(response->getBody());
-	if (! body || ! body->size())
-	{
-		return false;
-	}
+    // Convert response to LLSD
+    BufferArray * body(response->getBody());
+    if (!body || !body->size())
+    {
+        return false;
+    }
 
-	LLCore::BufferArrayStream bas(body);
-	LLSD body_llsd;
-	S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
-	if (LLSDParser::PARSE_FAILURE == parse_status){
-		return false;
-	}
-	out_llsd = body_llsd;
-	return true;
+    LLCore::BufferArrayStream bas(body);
+    LLSD body_llsd;
+    S32 parse_status(LLSDSerialize::fromXML(body_llsd, bas, log));
+    if (LLSDParser::PARSE_FAILURE == parse_status){
+        return false;
+    }
+    out_llsd = body_llsd;
+    return true;
 }
 
 
 HttpHandle requestPostWithLLSD(HttpRequest * request,
-							   HttpRequest::policy_t policy_id,
-							   HttpRequest::priority_t priority,
-							   const std::string & url,
-							   const LLSD & body,
-							   HttpOptions * options,
-							   HttpHeaders * headers,
-							   HttpHandler * handler)
+    HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const HttpOptions::ptr_t &options,
+    const HttpHeaders::ptr_t &headers,
+    HttpHandler * handler)
+{
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    BufferArray * ba = new BufferArray();
+    BufferArrayStream bas(ba);
+    LLSDSerialize::toXML(body, bas);
+
+    handle = request->requestPost(policy_id,
+        priority,
+        url,
+        ba,
+        options,
+        headers,
+        handler);
+    ba->release();
+    return handle;
+}
+
+
+HttpHandle requestPutWithLLSD(HttpRequest * request,
+    HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const HttpOptions::ptr_t &options,
+    const HttpHeaders::ptr_t &headers,
+    HttpHandler * handler)
+{
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+    BufferArray * ba = new BufferArray();
+    BufferArrayStream bas(ba);
+    LLSDSerialize::toXML(body, bas);
+
+    handle = request->requestPut(policy_id,
+        priority,
+        url,
+        ba,
+        options,
+        headers,
+        handler);
+    ba->release();
+    return handle;
+}
+
+HttpHandle requestPatchWithLLSD(HttpRequest * request,
+    HttpRequest::policy_t policy_id,
+    HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const HttpOptions::ptr_t &options,
+    const HttpHeaders::ptr_t &headers,
+    HttpHandler * handler)
 {
-	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+    HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
 
-	BufferArray * ba = new BufferArray();
-	BufferArrayStream bas(ba);
-	LLSDSerialize::toXML(body, bas);
+    BufferArray * ba = new BufferArray();
+    BufferArrayStream bas(ba);
+    LLSDSerialize::toXML(body, bas);
 
-	handle = request->requestPost(policy_id,
-								  priority,
-								  url,
-								  ba,
-								  options,
-								  headers,
-								  handler);
-	ba->release();
-	return handle;
+    handle = request->requestPatch(policy_id,
+        priority,
+        url,
+        ba,
+        options,
+        headers,
+        handler);
+    ba->release();
+    return handle;
 }
 
 
 std::string responseToString(LLCore::HttpResponse * response)
 {
-	static const std::string empty("[Empty]");
-
-	if (! response)
-	{
-		return empty;
-	}
-
-	BufferArray * body(response->getBody());
-	if (! body || ! body->size())
-	{
-		return empty;
-	}
-
-	// Attempt to parse as LLSD regardless of content-type
-	LLSD body_llsd;
-	if (responseToLLSD(response, false, body_llsd))
-	{
-		std::ostringstream tmp;
-
-		LLSDSerialize::toPrettyNotation(body_llsd, tmp);
-		std::size_t temp_len(tmp.tellp());
-		
-		if (temp_len)
-		{
-			return tmp.str().substr(0, std::min(temp_len, std::size_t(1024)));
-		}
-	}
-	else
-	{
-		// *TODO:  More elaborate forms based on Content-Type as needed.
-		char content[1024];
-
-		size_t len(body->read(0, content, sizeof(content)));
-		if (len)
-		{
-			return std::string(content, 0, len);
-		}
-	}
-
-	// Default
-	return empty;
+    static const std::string empty("[Empty]");
+
+    if (!response)
+    {
+        return empty;
+    }
+
+    BufferArray * body(response->getBody());
+    if (!body || !body->size())
+    {
+        return empty;
+    }
+
+    // Attempt to parse as LLSD regardless of content-type
+    LLSD body_llsd;
+    if (responseToLLSD(response, false, body_llsd))
+    {
+        std::ostringstream tmp;
+
+        LLSDSerialize::toPrettyNotation(body_llsd, tmp);
+        std::size_t temp_len(tmp.tellp());
+
+        if (temp_len)
+        {
+            return tmp.str().substr(0, std::min(temp_len, std::size_t(1024)));
+        }
+    }
+    else
+    {
+        // *TODO:  More elaborate forms based on Content-Type as needed.
+        char content[1024];
+
+        size_t len(body->read(0, content, sizeof(content)));
+        if (len)
+        {
+            return std::string(content, 0, len);
+        }
+    }
+
+    // Default
+    return empty;
+}
+
+//========================================================================
+
+HttpCoroHandler::HttpCoroHandler(LLEventStream &reply) :
+    mReplyPump(reply)
+{
+}
+
+void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+    LLSD result;
+
+    LLCore::HttpStatus status = response->getStatus();
+
+    if (status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_HANDLE_NOT_FOUND))
+    {   // A response came in for a canceled request and we have not processed the 
+        // cancel yet.  Patience!
+        return;
+    }
+
+    if (!status)
+    {
+        result = LLSD::emptyMap();
+        LL_WARNS()
+            << "\n--------------------------------------------------------------------------\n"
+            << " Error[" << status.getType() << "] cannot access url '" << response->getRequestURL()
+            << "' because " << status.toString()
+            << "\n--------------------------------------------------------------------------"
+            << LL_ENDL;
+    }
+    else
+    {
+        result = this->handleSuccess(response, status);
+    }
+
+    buildStatusEntry(response, status, result);
+
+#if 1
+    // commenting out, but keeping since this can be useful for debugging
+    if (!status)
+    {
+        LLSD &httpStatus = result[HttpCoroutineAdapter::HTTP_RESULTS];
+
+        LLCore::BufferArray *body = response->getBody();
+        LLCore::BufferArrayStream bas(body);
+        LLSD::String bodyData;
+        bodyData.reserve(response->getBodySize());
+        bas >> std::noskipws;
+        bodyData.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+        httpStatus["error_body"] = LLSD(bodyData);
+
+        LL_WARNS() << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
+    }
+#endif
+
+    mReplyPump.post(result);
+}
+
+void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result)
+{
+    LLSD httpresults = LLSD::emptyMap();
+
+    writeStatusCodes(status, response->getRequestURL(), httpresults);
+
+    LLSD httpHeaders = LLSD::emptyMap();
+    LLCore::HttpHeaders::ptr_t hdrs = response->getHeaders();
+
+    if (hdrs)
+    {
+        for (LLCore::HttpHeaders::iterator it = hdrs->begin(); it != hdrs->end(); ++it)
+        {
+            if (!(*it).second.empty())
+            {
+                httpHeaders[(*it).first] = (*it).second;
+            }
+            else
+            {
+                httpHeaders[(*it).first] = static_cast<LLSD::Boolean>(true);
+            }
+        }
+    }
+
+    httpresults[HttpCoroutineAdapter::HTTP_RESULTS_HEADERS] = httpHeaders;
+    result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults;
+}
+
+void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result)
+{
+    result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast<LLSD::Boolean>(status);
+    result[HttpCoroutineAdapter::HTTP_RESULTS_TYPE] = static_cast<LLSD::Integer>(status.getType());
+    result[HttpCoroutineAdapter::HTTP_RESULTS_STATUS] = static_cast<LLSD::Integer>(status.getStatus());
+    result[HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE] = static_cast<LLSD::String>(status.getMessage());
+    result[HttpCoroutineAdapter::HTTP_RESULTS_URL] = static_cast<LLSD::String>(url);
+
+}
+
+//=========================================================================
+/// The HttpCoroLLSDHandler is a specialization of the LLCore::HttpHandler for 
+/// interacting with coroutines. When the request is completed the response 
+/// will be posted onto the supplied Event Pump.
+/// 
+/// If the LLSD retrieved from through the HTTP connection is not in the form
+/// of a LLSD::map it will be returned as in an llsd["content"] element.
+/// 
+/// The LLSD posted back to the coroutine will have the following additions:
+/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
+///                      +- ["status"]  - The status code associated with the HTTP call
+///                      +- ["success"] - Success of failure of the HTTP call and LLSD parsing.
+///                      +- ["type"]    - The LLCore::HttpStatus type associted with the HTTP call
+///                      +- ["url"]     - The URL used to make the call.
+///                      +- ["headers"] - A map of name name value pairs with the HTTP headers.
+///                      
+class HttpCoroLLSDHandler : public HttpCoroHandler
+{
+public:
+    HttpCoroLLSDHandler(LLEventStream &reply);
+
+protected:
+    virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroLLSDHandler::HttpCoroLLSDHandler(LLEventStream &reply):
+    HttpCoroHandler(reply)
+{
+}
+    
+
+LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+    LLSD result;
+
+    const bool emit_parse_errors = false;
+
+    bool parsed = !((response->getBodySize() == 0) ||
+        !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, result));
+
+    if (!parsed)
+    {
+        // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+        LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+        const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+
+        if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+        {
+            std::string thebody = LLCoreHttpUtil::responseToString(response);
+            LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+                << " body: " << thebody << LL_ENDL;
+
+            // Replace the status with a new one indicating the failure.
+            status = LLCore::HttpStatus(499, "Failed to deserialize LLSD.");
+        }
+    }
+
+    if (result.isUndefined())
+    {   // If we've gotten to this point and the result LLSD is still undefined 
+        // either there was an issue deserializing the body or the response was
+        // blank.  Create an empty map to hold the result either way.
+        result = LLSD::emptyMap();
+    }
+    else if (!result.isMap())
+    {   // The results are not themselves a map.  Move them down so that 
+        // this method can return a map to the caller.
+        // *TODO: Should it always do this?
+        LLSD newResult = LLSD::emptyMap();
+        newResult[HttpCoroutineAdapter::HTTP_RESULTS_CONTENT] = result;
+        result = newResult;
+    }
+
+    return result;
+}
+
+//========================================================================
+/// The HttpCoroRawHandler is a specialization of the LLCore::HttpHandler for 
+/// interacting with coroutines. 
+/// 
+/// In addition to the normal "http_results" the returned LLSD will contain 
+/// an entry keyed with "raw" containing the unprocessed results of the HTTP
+/// call.
+///                      
+class HttpCoroRawHandler : public HttpCoroHandler
+{
+public:
+    HttpCoroRawHandler(LLEventStream &reply);
+
+    virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroRawHandler::HttpCoroRawHandler(LLEventStream &reply):
+    HttpCoroHandler(reply)
+{
+}
+
+LLSD HttpCoroRawHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+    LLSD result = LLSD::emptyMap();
+
+    BufferArray * body(response->getBody());
+    if (!body || !body->size())
+    {
+        return result;
+    }
+
+    size_t size = body->size();
+
+    LLCore::BufferArrayStream bas(body);
+
+#if 1
+    // This is the slower implementation.  It is safe vis-a-vi the const_cast<> and modification
+    // of a LLSD managed array but contains an extra (potentially large) copy.
+    // 
+    // *TODO: https://jira.secondlife.com/browse/MAINT-5221
+    
+    LLSD::Binary data;
+    data.reserve(size);
+    bas >> std::noskipws;
+    data.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+
+    result[HttpCoroutineAdapter::HTTP_RESULTS_RAW] = data;
+
+#else
+    // This is disabled because it's dangerous.  See the other case for an 
+    // alternate implementation.
+    // We create a new LLSD::Binary object and assign it to the result map.
+    // The LLSD has created it's own copy so we retrieve it asBinary and const cast 
+    // the reference so that we can modify it.
+    // *TODO: This is potentially dangerous... but I am trying to avoid a potentially 
+    // large copy.
+    result[HttpCoroutineAdapter::HTTP_RESULTS_RAW] = LLSD::Binary();
+    LLSD::Binary &data = const_cast<LLSD::Binary &>( result[HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary() );
+
+    data.reserve(size);
+    bas >> std::noskipws;
+    data.assign(std::istream_iterator<U8>(bas), std::istream_iterator<U8>());
+#endif
+
+    return result;
+}
+
+//========================================================================
+/// The HttpCoroJSONHandler is a specialization of the LLCore::HttpHandler for 
+/// interacting with coroutines. 
+/// 
+/// In addition to the normal "http_results" the returned LLSD will contain 
+/// JSON entries will be converted into an LLSD map.  All results are considered 
+/// strings
+///                      
+class HttpCoroJSONHandler : public HttpCoroHandler
+{
+public:
+    HttpCoroJSONHandler(LLEventStream &reply);
+
+    virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status);
+};
+
+//-------------------------------------------------------------------------
+HttpCoroJSONHandler::HttpCoroJSONHandler(LLEventStream &reply) :
+    HttpCoroHandler(reply)
+{
+}
+
+LLSD HttpCoroJSONHandler::handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status)
+{
+    LLSD result = LLSD::emptyMap();
+
+    BufferArray * body(response->getBody());
+    if (!body || !body->size())
+    {
+        return result;
+    }
+
+    LLCore::BufferArrayStream bas(body);
+    Json::Value jsonRoot;
+
+    try
+    {
+        bas >> jsonRoot;
+    }
+    catch (std::runtime_error e)
+    {   // deserialization failed.  Record the reason and pass back an empty map for markup.
+        status = LLCore::HttpStatus(499, std::string(e.what()));
+        return result;
+    }
+
+    // Convert the JSON structure to LLSD
+    result = LlsdFromJson(jsonRoot);
+
+    return result;
+}
+
+
+//========================================================================
+HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request) :
+    mHttpRequest(request)
+{
+    mBoundListener = LLEventPumps::instance().obtain("mainloop").
+        listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1));
+}
+
+HttpRequestPumper::~HttpRequestPumper()
+{
+    if (mBoundListener.connected())
+    {
+        mBoundListener.disconnect();
+    }
+}
+
+bool HttpRequestPumper::pollRequest(const LLSD&)
+{
+    if (mHttpRequest->getStatus() != HttpStatus(HttpStatus::LLCORE, HE_OP_CANCELED))
+    {
+        mHttpRequest->update(0L);
+    }
+    return false;
+}
+
+//========================================================================
+const std::string HttpCoroutineAdapter::HTTP_RESULTS("http_result");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS("success");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_TYPE("type");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_STATUS("status");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE("message");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_URL("url");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_HEADERS("headers");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content");
+const std::string HttpCoroutineAdapter::HTTP_RESULTS_RAW("raw");
+
+HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name,
+    LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) :
+    mAdapterName(name),
+    mPolicyId(policyId),
+    mPriority(priority),
+    mYieldingHandle(LLCORE_HTTP_HANDLE_INVALID),
+    mWeakRequest(),
+    mWeakHandler()
+{
+}
+
+HttpCoroutineAdapter::~HttpCoroutineAdapter()
+{
+    cancelSuspendedOperation();
+}
+
+LLSD HttpCoroutineAdapter::postAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return postAndSuspend_(request, url, body, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = requestPostWithLLSD(request,
+        mPolicyId, mPriority, url, body, options, headers,
+        handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::postAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return postAndSuspend_(request, url, rawbody, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::postRawAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroRawHandler(replyPump));
+
+    return postAndSuspend_(request, url, rawbody, options, headers, httpHandler);
+}
+
+// *TODO: This functionality could be moved into the LLCore::Http library itself 
+// by having the CURL layer read the file directly.
+LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, std::string fileName,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLCore::BufferArray::ptr_t fileData(new LLCore::BufferArray);
+
+    // scoping for our streams so that they go away when we no longer need them.
+    {
+        LLCore::BufferArrayStream outs(fileData.get());
+        llifstream ins(fileName.c_str(), std::iostream::binary | std::iostream::out);
+
+        if (ins.is_open())
+        {
+
+            ins.seekg(0, std::ios::beg);
+            ins >> std::noskipws;
+
+            std::copy(std::istream_iterator<U8>(ins), std::istream_iterator<U8>(),
+                    std::ostream_iterator<U8>(outs));
+
+            ins.close();
+        }
+    }
+
+    return postAndSuspend(request, url, fileData, options, headers);
+}
+
+// *TODO: This functionality could be moved into the LLCore::Http library itself 
+// by having the CURL layer read the file directly.
+LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLCore::BufferArray::ptr_t fileData(new LLCore::BufferArray);
+
+    // scoping for our streams so that they go away when we no longer need them.
+    {
+        LLCore::BufferArrayStream outs(fileData.get());
+        LLVFile vfile(gVFS, assetId, assetType, LLVFile::READ);
+
+        S32 fileSize = vfile.getSize();
+        U8* fileBuffer;
+        fileBuffer = new U8[fileSize];
+        vfile.read(fileBuffer, fileSize);
+        
+        outs.write((char*)fileBuffer, fileSize);
+        delete[] fileBuffer;
+    }
+
+    return postAndSuspend(request, url, fileData, options, headers);
+}
+
+LLSD HttpCoroutineAdapter::postJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroJSONHandler(replyPump));
+
+    LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
+
+    {
+        LLCore::BufferArrayStream outs(rawbody.get());
+        Json::Value root = LlsdToJson(body);
+        Json::FastWriter writer;
+
+        LL_WARNS("Http::post") << "JSON Generates: \"" << writer.write(root) << "\"" << LL_ENDL;
+
+        outs << writer.write(root);
+    }
+
+    return postAndSuspend_(request, url, rawbody, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(),
+        options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::putAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return putAndSuspend_(request, url, body, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::putJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroJSONHandler(replyPump));
+
+    LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
+
+    {
+        LLCore::BufferArrayStream outs(rawbody.get());
+        Json::Value root = LlsdToJson(body);
+        Json::FastWriter writer;
+
+        LL_WARNS("Http::put") << "JSON Generates: \"" << writer.write(root) << "\"" << LL_ENDL;
+        outs << writer.write(root);
+    }
+
+    return putAndSuspend_(request, url, rawbody, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = requestPutWithLLSD(request,
+        mPolicyId, mPriority, url, body, options, headers,
+        handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, const LLCore::BufferArray::ptr_t & rawbody,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = request->requestPut(mPolicyId, mPriority, 
+        url, rawbody.get(), options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+
+LLSD HttpCoroutineAdapter::getAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return getAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::getRawAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroRawHandler(replyPump));
+
+    return getAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::getJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroJSONHandler(replyPump));
+
+    return getAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::getAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers, 
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = request->requestGet(mPolicyId, mPriority,
+        url, options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+
+LLSD HttpCoroutineAdapter::deleteAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return deleteAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+LLSD HttpCoroutineAdapter::deleteJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, 
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroJSONHandler(replyPump));
+
+    return deleteAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, LLCore::HttpOptions::ptr_t &options, 
+    LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority,
+        url, options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::patchAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    return patchAndSuspend_(request, url, body, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::patchAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, const LLSD & body,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    LLCore::HttpHandle hhandle = requestPatchWithLLSD(request,
+        mPolicyId, mPriority, url, body, options, headers,
+        handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::copyAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const std::string dest,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    if (!headers)
+        headers.reset(new LLCore::HttpHeaders);
+    headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
+
+    return copyAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::copyAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url, 
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    // 
+    LLCore::HttpHandle hhandle = request->requestCopy(mPolicyId, mPriority, url,
+        options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+LLSD HttpCoroutineAdapter::moveAndSuspend(LLCore::HttpRequest::ptr_t request,
+    const std::string & url, const std::string dest,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName + "Reply", true);
+    HttpCoroHandler::ptr_t httpHandler(new HttpCoroLLSDHandler(replyPump));
+
+    if (!headers)
+        headers.reset(new LLCore::HttpHeaders);
+    headers->append(HTTP_OUT_HEADER_DESTINATION, dest);
+
+    return moveAndSuspend_(request, url, options, headers, httpHandler);
+}
+
+
+LLSD HttpCoroutineAdapter::moveAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+    const std::string & url,
+    LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+    HttpCoroHandler::ptr_t &handler)
+{
+    HttpRequestPumper pumper(request);
+
+    checkDefaultHeaders(headers);
+
+    // The HTTPCoroHandler does not self delete, so retrieval of a the contained 
+    // pointer from the smart pointer is safe in this case.
+    // 
+    LLCore::HttpHandle hhandle = request->requestMove(mPolicyId, mPriority, url,
+        options, headers, handler.get());
+
+    if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
+    {
+        return HttpCoroutineAdapter::buildImmediateErrorResult(request, url);
+    }
+
+    saveState(hhandle, request, handler);
+    LLSD results = llcoro::suspendUntilEventOn(handler->getReplyPump());
+    cleanState();
+
+    return results;
+}
+
+
+void HttpCoroutineAdapter::checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers)
+{
+    if (!headers)
+        headers.reset(new LLCore::HttpHeaders);
+    if (!headers->find(HTTP_OUT_HEADER_ACCEPT))
+    {
+        headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
+    }
+    if (!headers->find(HTTP_OUT_HEADER_CONTENT_TYPE))
+    {
+        headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+    }
+
+    if (!headers->find("X-SecondLife-UDP-Listen-Port") && gMessageSystem)
+    {
+        headers->append("X-SecondLife-UDP-Listen-Port", llformat("%d", gMessageSystem->mPort));
+    }
+}
+
+
+void HttpCoroutineAdapter::cancelSuspendedOperation()
+{
+    LLCore::HttpRequest::ptr_t request = mWeakRequest.lock();
+    HttpCoroHandler::ptr_t handler = mWeakHandler.lock();
+    if ((request) && (handler) && (mYieldingHandle != LLCORE_HTTP_HANDLE_INVALID))
+    {
+        cleanState();
+        LL_INFOS() << "Canceling yielding request!" << LL_ENDL;
+        request->requestCancel(mYieldingHandle, handler.get());
+    }
+}
+
+void HttpCoroutineAdapter::saveState(LLCore::HttpHandle yieldingHandle, 
+    LLCore::HttpRequest::ptr_t &request, HttpCoroHandler::ptr_t &handler)
+{
+    mWeakRequest = request;
+    mWeakHandler = handler;
+    mYieldingHandle = yieldingHandle;
+}
+
+void HttpCoroutineAdapter::cleanState()
+{
+    mWeakRequest.reset();
+    mWeakHandler.reset();
+    mYieldingHandle = LLCORE_HTTP_HANDLE_INVALID;
+}
+
+/*static*/
+LLSD HttpCoroutineAdapter::buildImmediateErrorResult(const LLCore::HttpRequest::ptr_t &request, 
+    const std::string &url) 
+{
+    LLCore::HttpStatus status = request->getStatus();
+    LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() <<
+        " message = " << status.getMessage() << LL_ENDL;
+
+    // Mimic the status results returned from an http error that we had 
+    // to wait on 
+    LLSD httpresults = LLSD::emptyMap();
+
+    HttpCoroHandler::writeStatusCodes(status, url, httpresults);
+
+    LLSD errorres = LLSD::emptyMap();
+    errorres["http_result"] = httpresults;
+
+    return errorres;
+}
+
+/*static*/
+LLCore::HttpStatus HttpCoroutineAdapter::getStatusFromLLSD(const LLSD &httpResults)
+{
+    LLCore::HttpStatus::type_enum_t type = static_cast<LLCore::HttpStatus::type_enum_t>(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_TYPE].asInteger());
+    short code = static_cast<short>(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_STATUS].asInteger());
+
+    return LLCore::HttpStatus(type, code);
+}
+
+/*static*/
+void HttpCoroutineAdapter::callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure)
+{
+    LLCoros::instance().launch("HttpCoroutineAdapter::genericGetCoro",
+        boost::bind(&HttpCoroutineAdapter::trivialGetCoro, url, policyId, success, failure));
+}
+
+/*static*/
+void HttpCoroutineAdapter::messageHttpGet(const std::string &url, const std::string &success, const std::string &failure)
+{
+    completionCallback_t cbSuccess = (success.empty()) ? NULL : 
+        static_cast<completionCallback_t>(boost::bind(&logMessageSuccess, "HttpCoroutineAdapter", url, success));
+    completionCallback_t cbFailure = (failure.empty()) ? NULL :
+        static_cast<completionCallback_t>(boost::bind(&logMessageFail, "HttpCoroutineAdapter", url, failure));
+    callbackHttpGet(url, cbSuccess, cbFailure);
+}
+
+/*static*/
+void HttpCoroutineAdapter::trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure)
+{
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericGetCoro", policyId));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+
+    LL_INFOS("HttpCoroutineAdapter", "genericGetCoro") << "Generic GET for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {   
+        if (failure)
+        {
+            failure(httpResults);
+        }
+    }
+    else
+    {
+        if (success)
+        {
+            success(result);
+        }
+    }
 }
 
+/*static*/
+void HttpCoroutineAdapter::callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success, completionCallback_t failure)
+{
+    LLCoros::instance().launch("HttpCoroutineAdapter::genericPostCoro",
+        boost::bind(&HttpCoroutineAdapter::trivialPostCoro, url, policyId, postData, success, failure));
+}
+
+/*static*/
+void HttpCoroutineAdapter::messageHttpPost(const std::string &url, const LLSD &postData, const std::string &success, const std::string &failure)
+{
+    completionCallback_t cbSuccess = (success.empty()) ? NULL :
+        static_cast<completionCallback_t>(boost::bind(&logMessageSuccess, "HttpCoroutineAdapter", url, success));
+    completionCallback_t cbFailure = (failure.empty()) ? NULL :
+        static_cast<completionCallback_t>(boost::bind(&logMessageFail, "HttpCoroutineAdapter", url, failure));
+
+    callbackHttpPost(url, postData, cbSuccess, cbFailure);
+}
+
+/*static*/
+void HttpCoroutineAdapter::trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure)
+{
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", policyId));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+
+    LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        // If a failure routine is provided do it.
+        if (failure)
+        {
+            failure(httpResults);
+        }
+    }
+    else
+    {
+        // If a success routine is provided do it.
+        if (success)
+        {
+            success(result);
+        }
+    }
+}
+
+
 
 } // end namespace LLCoreHttpUtil
 
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index d40172bc7a7865ec086bcfe3ea66d518bed0e780..9328427c341cb444e737349f6655519c9ddee759 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -36,9 +36,15 @@
 #include "httpheaders.h"
 #include "httpoptions.h"
 #include "httphandler.h"
+#include "llhttpconstants.h" // *TODO: move to llcorehttp
 #include "bufferarray.h"
 #include "bufferstream.h"
 #include "llsd.h"
+#include "llevents.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llassettype.h"
+#include "lluuid.h"
 
 ///
 /// The base llcorehttp library implements many HTTP idioms
@@ -51,6 +57,7 @@
 ///
 namespace LLCoreHttpUtil
 {
+    extern const F32 HTTP_REQUEST_EXPIRY_SECS;
 
 /// Attempt to convert a response object's contents to LLSD.
 /// It is expected that the response body will be of non-zero
@@ -101,15 +108,572 @@ std::string responseToString(LLCore::HttpResponse * response);
 ///						a now-useless HttpHandler object.
 ///
 LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
-									   LLCore::HttpRequest::policy_t policy_id,
-									   LLCore::HttpRequest::priority_t priority,
-									   const std::string & url,
-									   const LLSD & body,
-									   LLCore::HttpOptions * options,
-									   LLCore::HttpHeaders * headers,
-									   LLCore::HttpHandler * handler);
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const LLCore::HttpOptions::ptr_t &options,
+    const LLCore::HttpHeaders::ptr_t &headers,
+    LLCore::HttpHandler * handler);
 
-} // end namespace LLCoreHttpUtil
+inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
+	LLCore::HttpRequest::policy_t policy_id,
+	LLCore::HttpRequest::priority_t priority,
+	const std::string & url,
+	const LLSD & body,
+	const LLCore::HttpOptions::ptr_t & options,
+	const LLCore::HttpHeaders::ptr_t & headers,
+	LLCore::HttpHandler * handler)
+{
+    return requestPostWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    LLCore::HttpHandler * handler)
+{
+    LLCore::HttpOptions::ptr_t options;
+    LLCore::HttpHeaders::ptr_t headers;
+
+    return requestPostWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+
+/// Issue a standard HttpRequest::requestPut() call but using
+/// and LLSD object as the request body.  Conventions are the
+/// same as with that method.  Caller is expected to provide
+/// an HttpHeaders object with a correct 'Content-Type:' header.
+/// One will not be provided by this call.
+///
+/// @return				If request is successfully issued, the
+///						HttpHandle representing the request.
+///						On error, LLCORE_HTTP_HANDLE_INVALID
+///						is returned and caller can fetch detailed
+///						status with the getStatus() method on the
+///						request object.  In case of error, no
+///						request is queued and caller may need to
+///						perform additional cleanup such as freeing
+///						a now-useless HttpHandler object.
+///
+LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
+	LLCore::HttpRequest::policy_t policy_id,
+	LLCore::HttpRequest::priority_t priority,
+	const std::string & url,
+	const LLSD & body,
+	const LLCore::HttpOptions::ptr_t &options,
+	const LLCore::HttpHeaders::ptr_t &headers,
+	LLCore::HttpHandler * handler);
+
+inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
+	LLCore::HttpRequest::policy_t policy_id,
+	LLCore::HttpRequest::priority_t priority,
+	const std::string & url,
+	const LLSD & body,
+	const LLCore::HttpOptions::ptr_t & options,
+	const LLCore::HttpHeaders::ptr_t & headers,
+	LLCore::HttpHandler * handler)
+{
+    return requestPutWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    LLCore::HttpHandler * handler)
+{
+    LLCore::HttpOptions::ptr_t options;
+    LLCore::HttpHeaders::ptr_t headers;
+
+    return requestPutWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+/// Issue a standard HttpRequest::requestPatch() call but using
+/// and LLSD object as the request body.  Conventions are the
+/// same as with that method.  Caller is expected to provide
+/// an HttpHeaders object with a correct 'Content-Type:' header.
+/// One will not be provided by this call.
+///
+/// @return				If request is successfully issued, the
+///						HttpHandle representing the request.
+///						On error, LLCORE_HTTP_HANDLE_INVALID
+///						is returned and caller can fetch detailed
+///						status with the getStatus() method on the
+///						request object.  In case of error, no
+///						request is queued and caller may need to
+///						perform additional cleanup such as freeing
+///						a now-useless HttpHandler object.
+///
+LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const LLCore::HttpOptions::ptr_t &options,
+    const LLCore::HttpHeaders::ptr_t &headers,
+    LLCore::HttpHandler * handler);
+
+inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    const LLCore::HttpOptions::ptr_t & options,
+    const LLCore::HttpHeaders::ptr_t & headers,
+    LLCore::HttpHandler * handler)
+{
+    return requestPatchWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request,
+    LLCore::HttpRequest::policy_t policy_id,
+    LLCore::HttpRequest::priority_t priority,
+    const std::string & url,
+    const LLSD & body,
+    LLCore::HttpHandler * handler)
+{
+    LLCore::HttpOptions::ptr_t options;
+    LLCore::HttpHeaders::ptr_t headers;
+
+    return requestPatchWithLLSD(request.get(), policy_id, priority,
+        url, body, options, headers, handler);
+}
+
+//=========================================================================
+/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for 
+/// interacting with coroutines. When the request is completed the response 
+/// will be posted onto the supplied Event Pump.
+/// 
+/// The LLSD posted back to the coroutine will have the following additions:
+/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
+///                      +- ["status"]  - The status code associated with the HTTP call
+///                      +- ["success"] - Success of failure of the HTTP call and LLSD parsing.
+///                      +- ["type"]    - The LLCore::HttpStatus type associted with the HTTP call
+///                      +- ["url"]     - The URL used to make the call.
+///                      +- ["headers"] - A map of name name value pairs with the HTTP headers.
+///                      
+class HttpCoroHandler : public LLCore::HttpHandler
+{
+public:
+
+    typedef boost::shared_ptr<HttpCoroHandler>  ptr_t;
+    typedef boost::weak_ptr<HttpCoroHandler>    wptr_t;
+
+    HttpCoroHandler(LLEventStream &reply);
+
+    static void writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result);
+
+    virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+    inline LLEventStream &getReplyPump()
+    {
+        return mReplyPump;
+    }
+
+protected:
+    /// this method may modify the status value
+    virtual LLSD handleSuccess(LLCore::HttpResponse * response, LLCore::HttpStatus &status) = 0;
+
+private:
+    void buildStatusEntry(LLCore::HttpResponse *response, LLCore::HttpStatus status, LLSD &result);
 
+    LLEventStream &mReplyPump;
+};
+
+//=========================================================================
+/// An adapter to handle some of the boilerplate code surrounding HTTP and coroutine 
+/// interaction.
+/// 
+/// Construct an HttpCoroutineAdapter giving it a name and policy Id. After 
+/// any application specific setup call the post, put or get method.  The request 
+/// will be automatically pumped and the method will return with an LLSD describing
+/// the result of the operation.  See HttpCoroHandler for a description of the 
+/// decoration done to the returned LLSD.
+/// 
+/// Posting through the adapter will automatically add the following headers to 
+/// the request if they have not been previously specified in a supplied 
+/// HttpHeaders object:
+///     "Accept=application/llsd+xml"
+///     "X-SecondLife-UDP-Listen-Port=###"
+///     
+class HttpCoroutineAdapter
+{
+public:
+    static const std::string HTTP_RESULTS;
+    static const std::string HTTP_RESULTS_SUCCESS;
+    static const std::string HTTP_RESULTS_TYPE;
+    static const std::string HTTP_RESULTS_STATUS;
+    static const std::string HTTP_RESULTS_MESSAGE;
+    static const std::string HTTP_RESULTS_URL;
+    static const std::string HTTP_RESULTS_HEADERS;
+    static const std::string HTTP_RESULTS_CONTENT;
+    static const std::string HTTP_RESULTS_RAW;
+
+    typedef boost::shared_ptr<HttpCoroutineAdapter> ptr_t;
+    typedef boost::weak_ptr<HttpCoroutineAdapter>   wptr_t;
+
+    HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId,
+        LLCore::HttpRequest::priority_t priority = 0L);
+    ~HttpCoroutineAdapter();
+
+    /// Execute a Post transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available. 
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD postAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD postAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+    LLSD postAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postAndSuspend(request, url, body,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    LLSD postAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postAndSuspend(request, url, rawbody,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    LLSD postRawAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+    LLSD postRawAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postRawAndSuspend(request, url, rawbody,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    LLSD postFileAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, std::string fileName,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+    LLSD postFileAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, std::string fileName,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postFileAndSuspend(request, url, fileName,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+
+    LLSD postFileAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+    LLSD postFileAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLUUID assetId, LLAssetType::EType assetType,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postFileAndSuspend(request, url, assetId, assetType,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    LLSD postJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD postJsonAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postJsonAndSuspend(request, url, body,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+
+
+    /// Execute a Put transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available.
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD putAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+
+    LLSD putAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpHeaders::ptr_t headers)
+    {
+        return putAndSuspend(request, url, body,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    LLSD putJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD putJsonAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return putJsonAndSuspend(request, url, body,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    /// Execute a Get transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available.
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    /// 
+    LLSD getAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD getAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return getAndSuspend(request, url,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+            headers);
+    }
+
+    LLSD getRawAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD getRawAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return getRawAndSuspend(request, url,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+            headers);
+    }
+
+    /// These methods have the same behavior as @getAndSuspend() however they are 
+    /// expecting the server to return the results formatted in a JSON string. 
+    /// On a successful GET call the JSON results will be converted into LLSD 
+    /// before being returned to the caller.
+    LLSD getJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD getJsonAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return getJsonAndSuspend(request, url,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+            headers);
+    }
+
+
+    /// Execute a DELETE transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available.
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD deleteAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD deleteAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLCore::HttpHeaders::ptr_t headers)
+    {
+        return deleteAndSuspend(request, url,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+            headers);
+    }
+
+    /// These methods have the same behavior as @deleteAndSuspend() however they are 
+    /// expecting the server to return any results formatted in a JSON string. 
+    /// On a successful DELETE call the JSON results will be converted into LLSD 
+    /// before being returned to the caller.
+    LLSD deleteJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD deleteJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLCore::HttpHeaders::ptr_t headers)
+    {
+        return deleteJsonAndSuspend(request, url,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+            headers);
+    }
+
+
+    /// Execute a PATCH transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available. 
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD patchAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD patchAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return patchAndSuspend(request, url, body,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    /// Execute a COPY transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available. 
+    /// 
+    /// @Note: The destination is passed through the HTTP pipe as a header
+    /// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD copyAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const std::string dest,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD copyAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const std::string & dest,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return copyAndSuspend(request, url, dest,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    /// Execute a MOVE transaction on the supplied URL and yield execution of 
+    /// the coroutine until a result is available. 
+    /// 
+    /// @Note: The destination is passed through the HTTP pipe in the headers.
+    /// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
+    /// 
+    /// @Note: the request's smart pointer is passed by value so that it will
+    /// not be deallocated during the yield.
+    LLSD moveAndSuspend(LLCore::HttpRequest::ptr_t request,
+        const std::string & url, const std::string dest,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()));
+    LLSD moveAndSuspend(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const std::string & dest,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return moveAndSuspend(request, url, dest,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
+    }
+
+    ///
+    void cancelSuspendedOperation();
+
+    static LLCore::HttpStatus getStatusFromLLSD(const LLSD &httpResults);
+
+    /// The convenience routines below can be provided with callback functors 
+    /// which will be invoked in the case of success or failure.  These callbacks
+    /// should match this form.
+    /// @sa callbackHttpGet
+    /// @sa callbackHttpPost
+    typedef boost::function<void(const LLSD &)> completionCallback_t;
+
+    static void callbackHttpGet(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL, completionCallback_t failure = NULL);
+    static void callbackHttpGet(const std::string &url, completionCallback_t success = NULL, completionCallback_t failure = NULL)
+    {
+        callbackHttpGet(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, success, failure);
+    }
+    static void callbackHttpPost(const std::string &url, LLCore::HttpRequest::policy_t policyId, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL);
+    static void callbackHttpPost(const std::string &url, const LLSD &postData, completionCallback_t success = NULL, completionCallback_t failure = NULL)
+    {
+        callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure);
+    }
+
+    /// Generic Get and post routines for HTTP via coroutines.
+    /// These static methods do all required setup for the GET or POST operation.
+    /// When the operation completes successfully they will put the success message in the log at INFO level, 
+    /// If the operation fails the failure message is written to the log at WARN level.
+    /// 
+    static void messageHttpGet(const std::string &url, const std::string &success = std::string(), const std::string &failure = std::string());
+    static void messageHttpPost(const std::string &url, const LLSD &postData, const std::string &success, const std::string &failure);
+
+
+private:
+    static LLSD buildImmediateErrorResult(const LLCore::HttpRequest::ptr_t &request, const std::string &url);
+
+    void saveState(LLCore::HttpHandle yieldingHandle, LLCore::HttpRequest::ptr_t &request,
+            HttpCoroHandler::ptr_t &handler);
+    void cleanState();
+
+    LLSD postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD postAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD putAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLCore::BufferArray::ptr_t & rawbody,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD getAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::HttpOptions::ptr_t &options, 
+        LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler);
+
+    LLSD deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::HttpOptions::ptr_t &options,
+        LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler);
+
+    LLSD patchAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, const LLSD & body,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD copyAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, 
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    LLSD moveAndSuspend_(LLCore::HttpRequest::ptr_t &request,
+        const std::string & url,
+        LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
+        HttpCoroHandler::ptr_t &handler);
+
+    static void trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
+    static void trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure);
+
+    void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);
+
+    std::string                     mAdapterName;
+    LLCore::HttpRequest::priority_t mPriority;
+    LLCore::HttpRequest::policy_t   mPolicyId;
+
+    LLCore::HttpHandle              mYieldingHandle;
+    LLCore::HttpRequest::wptr_t     mWeakRequest;
+    HttpCoroHandler::wptr_t         mWeakHandler;
+};
+
+
+} // end namespace LLCoreHttpUtil
 
 #endif // LL_LLCOREHTTPUTIL_H
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
deleted file mode 100755
index 73df47b933f91db8f06d44ad450feb59025535f1..0000000000000000000000000000000000000000
--- a/indra/llmessage/llcurl.cpp
+++ /dev/null
@@ -1,2038 +0,0 @@
-/**
- * @file llcurl.cpp
- * @author Zero / Donovan
- * @date 2006-10-15
- * @brief Implementation of wrapper around libcurl.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010-2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if LL_WINDOWS
-#define SAFE_SSL 1
-#elif LL_DARWIN
-#define SAFE_SSL 1
-#else
-#define SAFE_SSL 1
-#endif
-
-#include "linden_common.h"
-
-#include "llcurl.h"
-
-#include <algorithm>
-#include <iomanip>
-#include <curl/curl.h>
-#if SAFE_SSL
-#include <openssl/crypto.h>
-#endif
-
-#include "llbufferstream.h"
-#include "llproxy.h"
-#include "llsdserialize.h"
-#include "llstl.h"
-#include "llstring.h"
-#include "llthread.h"
-#include "lltimer.h"
-
-//////////////////////////////////////////////////////////////////////////////
-/*
-	The trick to getting curl to do keep-alives is to reuse the
-	same easy handle for the requests.  It appears that curl
-	keeps a pool of connections alive for each easy handle, but
-	doesn't share them between easy handles.  Therefore it is
-	important to keep a pool of easy handles and reuse them,
-	rather than create and destroy them with each request.  This
-	code does this.
-
-	Furthermore, it would behoove us to keep track of which
-	hosts an easy handle was used for and pick an easy handle
-	that matches the next request.  This code does not current
-	do this.
- */
-
-//////////////////////////////////////////////////////////////////////////////
-
-static const U32 EASY_HANDLE_POOL_SIZE		= 5;
-static const S32 MULTI_PERFORM_CALL_REPEAT	= 5;
-static const S32 CURL_REQUEST_TIMEOUT = 120; // seconds per operation
-static const S32 CURL_CONNECT_TIMEOUT = 30; //seconds to wait for a connection
-static const S32 MAX_ACTIVE_REQUEST_COUNT = 100;
-
-// DEBUG //
-S32 gCurlEasyCount = 0;
-S32 gCurlMultiCount = 0;
-
-//////////////////////////////////////////////////////////////////////////////
-
-//static
-std::vector<LLMutex*> LLCurl::sSSLMutex;
-std::string LLCurl::sCAPath;
-std::string LLCurl::sCAFile;
-LLCurlThread* LLCurl::sCurlThread = NULL ;
-LLMutex* LLCurl::sHandleMutexp = NULL ;
-S32      LLCurl::sTotalHandles = 0 ;
-bool     LLCurl::sNotQuitting = true;
-F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds
-S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined).
-CURL*	 LLCurl::sCurlTemplateStandardHandle = NULL;
-
-void check_curl_code(CURLcode code)
-{
-	if (code != CURLE_OK)
-	{
-		// linux appears to throw a curl error once per session for a bad initialization
-		// at a pretty random time (when enabling cookies).
-		LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
-	}
-}
-
-void check_curl_multi_code(CURLMcode code) 
-{
-	if (code != CURLM_OK)
-	{
-		// linux appears to throw a curl error once per session for a bad initialization
-		// at a pretty random time (when enabling cookies).
-		LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
-	}
-}
-
-//static
-void LLCurl::setCAPath(const std::string& path)
-{
-	sCAPath = path;
-}
-
-//static
-void LLCurl::setCAFile(const std::string& file)
-{
-	sCAFile = file;
-}
-
-//static
-std::string LLCurl::getVersionString()
-{
-	return std::string(curl_version());
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-LLCurl::Responder::Responder()
-	: mHTTPMethod(HTTP_INVALID), mStatus(HTTP_INTERNAL_ERROR)
-{
-}
-
-LLCurl::Responder::~Responder()
-{
-	LL_CHECK_MEMORY
-}
-
-// virtual
-void LLCurl::Responder::httpFailure()
-{
-	LL_WARNS("curl") << dumpResponse() << LL_ENDL;
-}
-
-std::string LLCurl::Responder::dumpResponse() const 
-{
-	std::ostringstream s;
-	s << "[" << httpMethodAsVerb(mHTTPMethod) << ":" << mURL << "] "
-	  << "[status:" << mStatus << "] "
-	  << "[reason:" << mReason << "] ";
-
-	if (mResponseHeaders.has(HTTP_IN_HEADER_CONTENT_TYPE))
-	{
-		s << "[content-type:" << mResponseHeaders[HTTP_IN_HEADER_CONTENT_TYPE] << "] ";
-	}
-
-	s << "[content:" << mContent << "]";
-
-	return s.str();
-}
-
-// virtual
-void LLCurl::Responder::httpSuccess()
-{
-}
-
-void LLCurl::Responder::setURL(const std::string& url)
-{
-	mURL = url;
-}
-
-void LLCurl::Responder::successResult(const LLSD& content)
-{
-	setResult(HTTP_OK, "", content);
-	httpSuccess();
-}
-
-void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
-{
-	setResult(status, reason, content);
-	httpFailure();
-}
-
-void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
-{
-	setResult(status, reason, content);
-	httpCompleted();
-}
-
-void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
-{
-	mStatus = status;
-	mReason = reason;
-	mContent = content;
-}
-
-void LLCurl::Responder::setHTTPMethod(EHTTPMethod method)
-{
-	mHTTPMethod = method;
-}
-
-void LLCurl::Responder::setResponseHeader(const std::string& header, const std::string& value)
-{
-	mResponseHeaders[header] = value;
-}
-
-const std::string& LLCurl::Responder::getResponseHeader(const std::string& header) const
-{
-	if (mResponseHeaders.has(header))
-	{
-		return mResponseHeaders[header].asStringRef();
-	}
-	static const std::string empty;
-	return empty;
-}
-
-bool LLCurl::Responder::hasResponseHeader(const std::string& header) const
-{
-	if (mResponseHeaders.has(header)) return true;
-	return false;
-}
-
-// virtual
-void LLCurl::Responder::completedRaw(
-	const LLChannelDescriptors& channels,
-	const LLIOPipe::buffer_ptr_t& buffer)
-{
-	LLBufferStream istr(channels, buffer.get());
-	const bool emit_parse_errors = false;
-
-	std::string debug_body("(empty)");
-	bool parsed=true;
-	if (EOF == istr.peek())
-	{
-		parsed=false;
-	}
-	// Try to parse body as llsd, no matter what 'content-type' says.
-	else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors))
-	{
-		parsed=false;
-		char body[1025]; 
-		body[1024] = '\0';
-		istr.seekg(0, std::ios::beg);
-		istr.get(body,1024);
-		if (strlen(body) > 0)
-		{
-			mContent = body;
-			debug_body = body;
-		}
-	}
-
-	// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
-	if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
-	{
-		LL_WARNS() << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] " 
-			<< "(" << mReason << ") body: " << debug_body << LL_ENDL;
-	}
-
-	httpCompleted();
-}
-
-// virtual
-void LLCurl::Responder::httpCompleted()
-{
-	if (isGoodStatus())
-	{
-		httpSuccess();
-	}
-	else
-	{
-		httpFailure();
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-std::set<CURL*> LLCurl::Easy::sFreeHandles;
-std::set<CURL*> LLCurl::Easy::sActiveHandles;
-LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;
-
-//static
-CURL* LLCurl::Easy::allocEasyHandle()
-{
-	llassert(LLCurl::getCurlThread()) ;
-
-	CURL* ret = NULL;
-
-	LLMutexLock lock(sHandleMutexp) ;
-
-	if (sFreeHandles.empty())
-	{
-		ret = LLCurl::newEasyHandle();
-	}
-	else
-	{
-		ret = *(sFreeHandles.begin());
-		sFreeHandles.erase(ret);
-		curl_easy_reset(ret);
-	}
-
-	if (ret)
-	{
-		sActiveHandles.insert(ret);
-	}
-
-	return ret;
-}
-
-//static
-void LLCurl::Easy::releaseEasyHandle(CURL* handle)
-{
-	static const S32 MAX_NUM_FREE_HANDLES = 32 ;
-
-	if (!handle)
-	{
-		return ; //handle allocation failed.
-		//LL_ERRS() << "handle cannot be NULL!" << LL_ENDL;
-	}
-
-	LLMutexLock lock(sHandleMutexp) ;
-	if (sActiveHandles.find(handle) != sActiveHandles.end())
-	{
-		LL_CHECK_MEMORY
-		sActiveHandles.erase(handle);
-		LL_CHECK_MEMORY
-		if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES)
-		{
-			sFreeHandles.insert(handle);
-			LL_CHECK_MEMORY
-		}
-		else
-		{
-			LLCurl::deleteEasyHandle(handle) ;
-			LL_CHECK_MEMORY
-		}
-	}
-	else
-	{
-		LL_ERRS() << "Invalid handle." << LL_ENDL;
-	}
-}
-
-//static
-void LLCurl::Easy::deleteAllActiveHandles()
-{
-	LLMutexLock lock(sHandleMutexp) ;
-	LL_CHECK_MEMORY
-	for (std::set<CURL*>::iterator activeHandle = sActiveHandles.begin(); activeHandle != sActiveHandles.end(); ++activeHandle)
-	{
-		CURL* curlHandle = *activeHandle;
-		LLCurl::deleteEasyHandle(curlHandle);
-		LL_CHECK_MEMORY
-	}
-
-	sFreeHandles.clear();
-}
-
-//static
-void LLCurl::Easy::deleteAllFreeHandles()
-{
-	LLMutexLock lock(sHandleMutexp) ;
-	LL_CHECK_MEMORY
-	for (std::set<CURL*>::iterator freeHandle = sFreeHandles.begin(); freeHandle != sFreeHandles.end(); ++freeHandle)
-	{
-		CURL* curlHandle = *freeHandle;
-		LLCurl::deleteEasyHandle(curlHandle);
-		LL_CHECK_MEMORY
-	}
-
-	sFreeHandles.clear();
-}
-
-LLCurl::Easy::Easy()
-	: mHeaders(NULL),
-	  mCurlEasyHandle(NULL)
-{
-	mErrorBuffer[0] = 0;
-}
-
-LLCurl::Easy* LLCurl::Easy::getEasy()
-{
-	Easy* easy = new Easy();
-	easy->mCurlEasyHandle = allocEasyHandle(); 
-	
-	if (!easy->mCurlEasyHandle)
-	{
-		// this can happen if we have too many open files (fails in c-ares/ares_init.c)
-		LL_WARNS("curl") << "allocEasyHandle() returned NULL! Easy handles: " 
-			<< gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
-		delete easy;
-		return NULL;
-	}
-	
-	// Enable a brief cache period for now.  This was zero for the longest time
-	// which caused some routers grief and generated unneeded traffic.  For the
-	// threaded resolver, we're using system resolution libraries and non-zero values
-	// are preferred.  The c-ares resolver is another matter and it might not
-	// track server changes as well.
-	CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
-	check_curl_code(result);
-	result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-	check_curl_code(result);
-	
-	++gCurlEasyCount;
-	return easy;
-}
-
-LLCurl::Easy::~Easy()
-{
-	releaseEasyHandle(mCurlEasyHandle);
-	--gCurlEasyCount;
-	curl_slist_free_all(mHeaders);
-	LL_CHECK_MEMORY
-	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
-	LL_CHECK_MEMORY
-	if (mResponder && LLCurl::sNotQuitting) //aborted
-	{
-		// HTTP_REQUEST_TIME_OUT, timeout, abort
-		// *TODO: This looks like improper use of the 408 status code.
-		// See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9
-		// This status code should be returned by the *server* when:
-		// "The client did not produce a request within the time that the server was prepared to wait."
-		mResponder->setResult(HTTP_REQUEST_TIME_OUT, "Request timeout, aborted.");
-		mResponder->completedRaw(mChannels, mOutput);
-		LL_CHECK_MEMORY
-	}
-	mResponder = NULL;
-}
-
-void LLCurl::Easy::resetState()
-{
- 	curl_easy_reset(mCurlEasyHandle);
-
-	if (mHeaders)
-	{
-		curl_slist_free_all(mHeaders);
-		mHeaders = NULL;
-	}
-
-	mRequest.str("");
-	mRequest.clear();
-
-	mOutput.reset();
-	
-	mInput.str("");
-	mInput.clear();
-	
-	mErrorBuffer[0] = 0;
-	
-	mHeaderOutput.str("");
-	mHeaderOutput.clear();
-}
-
-void LLCurl::Easy::setErrorBuffer()
-{
-	setopt(CURLOPT_ERRORBUFFER, &mErrorBuffer);
-}
-
-const char* LLCurl::Easy::getErrorBuffer()
-{
-	return mErrorBuffer;
-}
-
-void LLCurl::Easy::setCA()
-{
-	if (!sCAPath.empty())
-	{
-		setoptString(CURLOPT_CAPATH, sCAPath);
-	}
-	if (!sCAFile.empty())
-	{
-		setoptString(CURLOPT_CAINFO, sCAFile);
-	}
-}
-
-void LLCurl::Easy::setHeaders()
-{
-	setopt(CURLOPT_HTTPHEADER, mHeaders);
-}
-
-void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info)
-{
-	check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SIZE_DOWNLOAD, &info->mSizeDownload));
-	check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_TOTAL_TIME, &info->mTotalTime));
-	check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload));
-}
-
-S32 LLCurl::Easy::report(CURLcode code)
-{
-	S32 responseCode = 0;
-	std::string responseReason;
-	
-	if (code == CURLE_OK)
-	{
-		check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode));
-		//*TODO: get reason from first line of mHeaderOutput
-	}
-	else
-	{
-		responseCode = HTTP_INTERNAL_ERROR;
-		responseReason = strerror(code) + " : " + mErrorBuffer;
-		setopt(CURLOPT_FRESH_CONNECT, TRUE);
-	}
-
-	if (mResponder)
-	{	
-		mResponder->setResult(responseCode, responseReason);
-		mResponder->completedRaw(mChannels, mOutput);
-		mResponder = NULL;
-	}
-	
-	resetState();
-	return responseCode;
-}
-
-// Note: these all assume the caller tracks the value (i.e. keeps it persistant)
-void LLCurl::Easy::setopt(CURLoption option, S32 value)
-{
-	CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value);
-	check_curl_code(result);
-}
-
-void LLCurl::Easy::setopt(CURLoption option, void* value)
-{
-	CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value);
-	check_curl_code(result);
-}
-
-void LLCurl::Easy::setopt(CURLoption option, char* value)
-{
-	CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value);
-	check_curl_code(result);
-}
-
-// Note: this copies the string so that the caller does not have to keep it around
-void LLCurl::Easy::setoptString(CURLoption option, const std::string& value)
-{
-	char* tstring = new char[value.length()+1];
-	strcpy(tstring, value.c_str());
-	mStrings.push_back(tstring);
-	CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, tstring);
-	check_curl_code(result);
-}
-
-void LLCurl::Easy::slist_append(const std::string& header, const std::string& value)
-{
-	std::string pair(header);
-	if (value.empty())
-	{
-		pair += ":";
-	}
-	else
-	{
-		pair += ": ";
-		pair += value;
-	}
-	slist_append(pair.c_str());
-}
-
-void LLCurl::Easy::slist_append(const char* str)
-{
-	if (str)
-	{
-		mHeaders = curl_slist_append(mHeaders, str);
-		if (!mHeaders)
-		{
-			LL_WARNS() << "curl_slist_append() call returned NULL appending " << str << LL_ENDL;
-		}
-	}
-}
-
-size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)
-{
-	LLCurl::Easy* easy = (LLCurl::Easy*)user_data;
-	
-	S32 n = size * nmemb;
-	S32 startpos = (S32)easy->getInput().tellg();
-	easy->getInput().seekg(0, std::ios::end);
-	S32 endpos = (S32)easy->getInput().tellg();
-	easy->getInput().seekg(startpos, std::ios::beg);
-	S32 maxn = endpos - startpos;
-	n = llmin(n, maxn);
-	easy->getInput().read((char*)data, n);
-
-	return n;
-}
-
-size_t curlWriteCallback(char* data, size_t size, size_t nmemb, void* user_data)
-{
-	LLCurl::Easy* easy = (LLCurl::Easy*)user_data;
-	
-	S32 n = size * nmemb;
-	easy->getOutput()->append(easy->getChannels().in(), (const U8*)data, n);
-
-	return n;
-}
-
-size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data)
-{
-	LLCurl::Easy* easy = (LLCurl::Easy*)user_data;
-	
-	size_t n = size * nmemb;
-	easy->getHeaderOutput().write((const char*)data, n);
-
-	return n;
-}
-
-void LLCurl::Easy::prepRequest(const std::string& url,
-							   const std::vector<std::string>& headers,
-							   ResponderPtr responder, S32 time_out, bool post)
-{
-	resetState();
-	
-	if (post) setoptString(CURLOPT_ENCODING, "");
-
-	//setopt(CURLOPT_VERBOSE, 1); // useful for debugging
-	setopt(CURLOPT_NOSIGNAL, 1);
-	setopt(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-	
-	// Set the CURL options for either Socks or HTTP proxy
-	LLProxy::getInstance()->applyProxySettings(this);
-
-	mOutput.reset(new LLBufferArray);
-	mOutput->setThreaded(true);
-	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);
-	setopt(CURLOPT_WRITEDATA, (void*)this);
-
-	setopt(CURLOPT_READFUNCTION, (void*)&curlReadCallback);
-	setopt(CURLOPT_READDATA, (void*)this);
-	
-	setopt(CURLOPT_HEADERFUNCTION, (void*)&curlHeaderCallback);
-	setopt(CURLOPT_HEADERDATA, (void*)this);
-
-	// Allow up to five redirects
-	if (responder && responder->followRedir())
-	{
-		setopt(CURLOPT_FOLLOWLOCATION, 1);
-		setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS);
-	}
-
-	setErrorBuffer();
-	setCA();
-
-	setopt(CURLOPT_SSL_VERIFYPEER, true);
-	
-	//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
-	setopt(CURLOPT_SSL_VERIFYHOST, 0);
-	setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT));
-	setopt(CURLOPT_CONNECTTIMEOUT, CURL_CONNECT_TIMEOUT);
-
-	setoptString(CURLOPT_URL, url);
-
-	mResponder = responder;
-
-	if (!post)
-	{
-		// *TODO: Should this be set to 'Keep-Alive' ?
-		slist_append(HTTP_OUT_HEADER_CONNECTION, "keep-alive");
-		slist_append(HTTP_OUT_HEADER_KEEP_ALIVE, "300");
-		// Accept and other headers
-		for (std::vector<std::string>::const_iterator iter = headers.begin();
-			 iter != headers.end(); ++iter)
-		{
-			slist_append((*iter).c_str());
-		}
-	}
-}
-
-////////////////////////////////////////////////////////////////////////////
-LLCurl::Multi::Multi(F32 idle_time_out)
-	: mQueued(0),
-	  mErrorCount(0),
-	  mState(STATE_READY),
-	  mDead(FALSE),
-	  mValid(TRUE),
-	  mMutexp(NULL),
-	  mDeletionMutexp(NULL),
-	  mEasyMutexp(NULL)
-{
-	mCurlMultiHandle = LLCurl::newMultiHandle();
-	if (!mCurlMultiHandle)
-	{
-		LL_WARNS() << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
-		mCurlMultiHandle = LLCurl::newMultiHandle();
-	}
-	
-	//llassert_always(mCurlMultiHandle);	
-
-	if(mCurlMultiHandle)
-	{
-	if(LLCurl::getCurlThread()->getThreaded())
-	{
-		mMutexp = new LLMutex(NULL) ;
-		mDeletionMutexp = new LLMutex(NULL) ;
-		mEasyMutexp = new LLMutex(NULL) ;
-	}
-	LLCurl::getCurlThread()->addMulti(this) ;
-
-		mIdleTimeOut = idle_time_out ;
-		if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut)
-		{
-			mIdleTimeOut = LLCurl::sCurlRequestTimeOut ;
-		}
-
-	++gCurlMultiCount;
-}
-}
-
-LLCurl::Multi::~Multi()
-{
-	cleanup(true) ;	
-	
-	delete mDeletionMutexp ;
-	mDeletionMutexp = NULL ;	
-}
-
-void LLCurl::Multi::cleanup(bool deleted)
-{
-	if(!mCurlMultiHandle)
-	{
-		return ; //nothing to clean.
-	}
-	llassert_always(deleted || !mValid) ;
-
-	LLMutexLock lock(mDeletionMutexp);
-
-
-	// Clean up active
-	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
-		iter != mEasyActiveList.end(); ++iter)
-	{
-		Easy* easy = *iter;
-		LL_CHECK_MEMORY
-		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
-		LL_CHECK_MEMORY
-		if(deleted)
-		{
-			easy->mResponder = NULL ; //avoid triggering mResponder.
-			LL_CHECK_MEMORY
-		}
-		delete easy;
-		LL_CHECK_MEMORY
-	}
-	mEasyActiveList.clear();
-	mEasyActiveMap.clear();
-	
-	LL_CHECK_MEMORY
-	
-		// Clean up freed
-	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	
-	mEasyFreeList.clear();
-	
-	LL_CHECK_MEMORY
-		
-	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle));
-	mCurlMultiHandle = NULL ;
-
-	LL_CHECK_MEMORY
-	
-	delete mMutexp ;
-	mMutexp = NULL ;
-
-	LL_CHECK_MEMORY
-
-	delete mEasyMutexp ;
-	mEasyMutexp = NULL ;
-
-	LL_CHECK_MEMORY
-
-	mQueued = 0 ;
-	mState = STATE_COMPLETED;
-	
-	--gCurlMultiCount;
-
-	return ;
-}
-
-void LLCurl::Multi::lock()
-{
-	if(mMutexp)
-	{
-		mMutexp->lock() ;
-	}
-}
-
-void LLCurl::Multi::unlock()
-{
-	if(mMutexp)
-	{
-		mMutexp->unlock() ;
-	}
-}
-
-void LLCurl::Multi::markDead()
-{
-	{
-		LLMutexLock lock(mDeletionMutexp) ;
-	
-		if(mCurlMultiHandle != NULL)
-		{
-			mDead = TRUE ;
-			LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; 
-
-			return;
-		}
-	}
-	
-	//not valid, delete it.
-	delete this;	
-}
-
-void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state)
-{
-	lock() ;
-	mState = state ;
-	unlock() ;
-
-	if(mState == STATE_READY)
-	{
-		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ;
-	}	
-}
-
-LLCurl::Multi::ePerformState LLCurl::Multi::getState()
-{
-	return mState;
-}
-	
-bool LLCurl::Multi::isCompleted() 
-{
-	return STATE_COMPLETED == getState() ;
-}
-
-bool LLCurl::Multi::waitToComplete()
-{
-	if(!isValid())
-	{
-		return true ;
-	}
-
-	if(!mMutexp) //not threaded
-	{
-		doPerform() ;
-		return true ;
-	}
-
-	bool completed = (STATE_COMPLETED == mState) ;
-	if(!completed)
-	{
-		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ;
-	}
-	
-	return completed;
-}
-
-CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
-{
-	LLMutexLock lock(mMutexp) ;
-
-	CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue);
-	return curlmsg;
-}
-
-//return true if dead
-bool LLCurl::Multi::doPerform()
-{
-	LLMutexLock lock(mDeletionMutexp) ;
-	
-	bool dead = mDead ;
-
-	if(mDead)
-	{
-		setState(STATE_COMPLETED);
-		mQueued = 0 ;
-	}
-	else if(getState() != STATE_COMPLETED)
-	{		
-		setState(STATE_PERFORMING);
-
-		S32 q = 0;
-		for (S32 call_count = 0;
-				call_count < MULTI_PERFORM_CALL_REPEAT;
-				call_count++)
-		{
-			LLMutexLock lock(mMutexp) ;
-
-			//WARNING: curl_multi_perform will block for many hundreds of milliseconds
-			// NEVER call this from the main thread, and NEVER allow the main thread to 
-			// wait on a mutex held by this thread while curl_multi_perform is executing
-			CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
-			if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
-			{
-				check_curl_multi_code(code);
-			
-				break;
-			}
-		}
-
-		mQueued = q;	
-		setState(STATE_COMPLETED) ;
-		mIdleTimer.reset() ;
-	}
-	else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it.
-	{
-		dead = true ;
-	}
-	else if(mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut - 1.f) //idle for too long, mark it invalid.
-	{
-		mValid = FALSE ;
-	}
-
-	return dead ;
-}
-
-S32 LLCurl::Multi::process()
-{
-	if(!isValid())
-	{
-		return 0 ;
-	}
-
-	waitToComplete() ;
-
-	if (getState() != STATE_COMPLETED)
-	{
-		return 0;
-	}
-
-	CURLMsg* msg;
-	int msgs_in_queue;
-
-	S32 processed = 0;
-	while ((msg = info_read(&msgs_in_queue)))
-	{
-		++processed;
-		if (msg->msg == CURLMSG_DONE)
-		{
-			S32 response = 0;
-			Easy* easy = NULL ;
-
-			{
-				LLMutexLock lock(mEasyMutexp) ;
-				easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle);
-				if (iter != mEasyActiveMap.end())
-				{
-					easy = iter->second;
-				}
-			}
-
-			if(easy)
-			{
-				response = easy->report(msg->data.result);
-				removeEasy(easy);
-			}
-			else
-			{
-				response = HTTP_INTERNAL_ERROR;
-				//*TODO: change to LL_WARNS()
-				LL_ERRS() << "cleaned up curl request completed!" << LL_ENDL;
-			}
-			if (response >= 400)
-			{
-				// failure of some sort, inc mErrorCount for debugging and flagging multi for destruction
-				++mErrorCount;
-			}
-		}
-	}
-
-	setState(STATE_READY);
-
-	return processed;
-}
-
-LLCurl::Easy* LLCurl::Multi::allocEasy()
-{
-	Easy* easy = 0;	
-
-	if (mEasyFreeList.empty())
-	{		
-		easy = Easy::getEasy();
-	}
-	else
-	{
-		LLMutexLock lock(mEasyMutexp) ;
-		easy = *(mEasyFreeList.begin());
-		mEasyFreeList.erase(easy);
-	}
-	if (easy)
-	{
-		LLMutexLock lock(mEasyMutexp) ;
-		mEasyActiveList.insert(easy);
-		mEasyActiveMap[easy->getCurlHandle()] = easy;
-	}
-	return easy;
-}
-
-bool LLCurl::Multi::addEasy(Easy* easy)
-{
-	LLMutexLock lock(mMutexp) ;
-	CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle());
-	check_curl_multi_code(mcode);
-	//if (mcode != CURLM_OK)
-	//{
-	//	LL_WARNS() << "Curl Error: " << curl_multi_strerror(mcode) << LL_ENDL;
-	//	return false;
-	//}
-	return true;
-}
-
-void LLCurl::Multi::easyFree(Easy* easy)
-{
-	if(mEasyMutexp)
-	{
-		mEasyMutexp->lock() ;
-	}
-
-	mEasyActiveList.erase(easy);
-	mEasyActiveMap.erase(easy->getCurlHandle());
-
-	if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE)
-	{		
-		mEasyFreeList.insert(easy);
-		
-		if(mEasyMutexp)
-		{
-			mEasyMutexp->unlock() ;
-		}
-
-		easy->resetState();
-	}
-	else
-	{
-		if(mEasyMutexp)
-		{
-			mEasyMutexp->unlock() ;
-		}
-		delete easy;
-	}
-}
-
-void LLCurl::Multi::removeEasy(Easy* easy)
-{
-	{
-		LLMutexLock lock(mMutexp) ;
-		check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()));
-	}
-	easyFree(easy);
-}
-
-//------------------------------------------------------------
-//LLCurlThread
-LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) :
-	LLQueuedThread::QueuedRequest(handle, LLQueuedThread::PRIORITY_NORMAL, FLAG_AUTO_COMPLETE),
-	mMulti(multi),
-	mCurlThread(curl_thread)
-{	
-}
-
-LLCurlThread::CurlRequest::~CurlRequest()
-{	
-	if(mMulti)
-	{
-		mCurlThread->deleteMulti(mMulti) ;
-		mMulti = NULL ;
-	}
-}
-
-bool LLCurlThread::CurlRequest::processRequest()
-{
-	bool completed = true ;
-	if(mMulti)
-	{
-		completed = mCurlThread->doMultiPerform(mMulti) ;
-
-		if(!completed)
-		{
-			setPriority(LLQueuedThread::PRIORITY_LOW) ;
-		}
-	}
-
-	return completed ;
-}
-
-void LLCurlThread::CurlRequest::finishRequest(bool completed)
-{
-	if(mMulti->isDead())
-	{
-		mCurlThread->deleteMulti(mMulti) ;
-	}
-	else
-	{
-		mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request.
-	}
-
-	mMulti = NULL ;
-}
-	
-LLCurlThread::LLCurlThread(bool threaded) :
-	LLQueuedThread("curlthread", threaded)
-{
-}
-	
-//virtual 
-LLCurlThread::~LLCurlThread() 
-{
-}
-
-S32 LLCurlThread::update(F32 max_time_ms)
-{	
-	return LLQueuedThread::update(max_time_ms);
-}
-
-void LLCurlThread::addMulti(LLCurl::Multi* multi)
-{
-	multi->mHandle = generateHandle() ;
-
-	CurlRequest* req = new CurlRequest(multi->mHandle, multi, this) ;
-
-	if (!addRequest(req))
-	{
-		LL_WARNS() << "curl request added when the thread is quitted" << LL_ENDL;
-	}
-}
-	
-void LLCurlThread::killMulti(LLCurl::Multi* multi)
-{
-	if(!multi)
-	{
-		return ;
-	}
-
-
-	multi->markDead() ;
-}
-
-//private
-bool LLCurlThread::doMultiPerform(LLCurl::Multi* multi) 
-{
-	return multi->doPerform() ;
-}
-
-//private
-void LLCurlThread::deleteMulti(LLCurl::Multi* multi) 
-{
-	delete multi ;
-}
-
-//private
-void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) 
-{
-	multi->cleanup() ;
-	if(multi->isDead()) //check if marked dead during cleaning up.
-	{
-		deleteMulti(multi) ;
-	}
-}
-
-//------------------------------------------------------------
-
-//static
-std::string LLCurl::strerror(CURLcode errorcode)
-{
-	return std::string(curl_easy_strerror(errorcode));
-}
-
-////////////////////////////////////////////////////////////////////////////
-// For generating a simple request for data
-// using one multi and one easy per request 
-
-LLCurlRequest::LLCurlRequest() :
-	mActiveMulti(NULL),
-	mActiveRequestCount(0)
-{
-	mProcessing = FALSE;
-}
-
-LLCurlRequest::~LLCurlRequest()
-{
-	//stop all Multi handle background threads
-	for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
-	{
-		LLCurl::getCurlThread()->killMulti(*iter) ;
-	}
-	mMultiSet.clear() ;
-}
-
-void LLCurlRequest::addMulti()
-{
-	LLCurl::Multi* multi = new LLCurl::Multi();
-	if(!multi->isValid())
-	{
-		LLCurl::getCurlThread()->killMulti(multi) ;
-		mActiveMulti = NULL ;
-		mActiveRequestCount = 0 ;
-		return;
-	}
-	
-	mMultiSet.insert(multi);
-	mActiveMulti = multi;
-	mActiveRequestCount = 0;
-}
-
-LLCurl::Easy* LLCurlRequest::allocEasy()
-{
-	if (!mActiveMulti ||
-		mActiveRequestCount	>= MAX_ACTIVE_REQUEST_COUNT ||
-		mActiveMulti->mErrorCount > 0)
-	{
-		addMulti();
-	}
-	if(!mActiveMulti)
-	{
-		return NULL ;
-	}
-
-	//llassert_always(mActiveMulti);
-	++mActiveRequestCount;
-	LLCurl::Easy* easy = mActiveMulti->allocEasy();
-	return easy;
-}
-
-bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
-{
-	llassert_always(mActiveMulti);
-	
-	if (mProcessing)
-	{
-		LL_ERRS() << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << LL_ENDL;
-	}
-	bool res = mActiveMulti->addEasy(easy);
-	return res;
-}
-
-void LLCurlRequest::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
-	getByteRange(url, headers_t(), 0, -1, responder);
-}
-
-// Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
-// the remainder of the file if not.
-bool LLCurlRequest::getByteRange(const std::string& url,
-								 const headers_t& headers,
-								 S32 offset, S32 length,
-								 LLCurl::ResponderPtr responder)
-{
-	llassert(LLCurl::sNotQuitting);
-	LLCurl::Easy* easy = allocEasy();
-	if (!easy)
-	{
-		return false;
-	}
-	easy->prepRequest(url, headers, responder);
-	easy->setopt(CURLOPT_HTTPGET, 1);
-	if (length > 0)
-	{
-		std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
-		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
-	}
-	else if (offset > 0)
-	{
-		std::string range = llformat("bytes=%d-", offset);
-		easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
-	}
-	easy->setHeaders();
-	bool res = addEasy(easy);
-	return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
-						 const headers_t& headers,
-						 const LLSD& data,
-						 LLCurl::ResponderPtr responder, S32 time_out)
-{
-	llassert(LLCurl::sNotQuitting);
-	LLCurl::Easy* easy = allocEasy();
-	if (!easy)
-	{
-		return false;
-	}
-	easy->prepRequest(url, headers, responder, time_out);
-
-	LLSDSerialize::toXML(data, easy->getInput());
-	S32 bytes = easy->getInput().str().length();
-	
-	easy->setopt(CURLOPT_POST, 1);
-	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
-	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
-	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
-	easy->setHeaders();
-
-	LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
-	bool res = addEasy(easy);
-	return res;
-}
-
-bool LLCurlRequest::post(const std::string& url,
-						 const headers_t& headers,
-						 const std::string& data,
-						 LLCurl::ResponderPtr responder, S32 time_out)
-{
-	llassert(LLCurl::sNotQuitting);
-	LLCurl::Easy* easy = allocEasy();
-	if (!easy)
-	{
-		return false;
-	}
-	easy->prepRequest(url, headers, responder, time_out);
-
-	easy->getInput().write(data.data(), data.size());
-	S32 bytes = easy->getInput().str().length();
-	
-	easy->setopt(CURLOPT_POST, 1);
-	easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
-	easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
-
-	easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
-	easy->setHeaders();
-
-	LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
-	bool res = addEasy(easy);
-	return res;
-}
-
-// Note: call once per frame
-S32 LLCurlRequest::process()
-{
-	S32 res = 0;
-
-	mProcessing = TRUE;
-	for (curlmulti_set_t::iterator iter = mMultiSet.begin();
-		 iter != mMultiSet.end(); )
-	{
-		curlmulti_set_t::iterator curiter = iter++;
-		LLCurl::Multi* multi = *curiter;
-
-		if(!multi->isValid())
-		{
-			if(multi == mActiveMulti)
-			{				
-				mActiveMulti = NULL ;
-				mActiveRequestCount = 0 ;
-			}
-			mMultiSet.erase(curiter) ;
-			LLCurl::getCurlThread()->killMulti(multi) ;
-			continue ;
-		}
-
-		S32 tres = multi->process();
-		res += tres;
-		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
-		{
-			mMultiSet.erase(curiter);
-			LLCurl::getCurlThread()->killMulti(multi);
-		}
-	}
-	mProcessing = FALSE;
-	return res;
-}
-
-S32 LLCurlRequest::getQueued()
-{
-	S32 queued = 0;
-	for (curlmulti_set_t::iterator iter = mMultiSet.begin();
-		 iter != mMultiSet.end(); )
-	{
-		curlmulti_set_t::iterator curiter = iter++;
-		LLCurl::Multi* multi = *curiter;
-		
-		if(!multi->isValid())
-		{
-			if(multi == mActiveMulti)
-			{				
-				mActiveMulti = NULL ;
-				mActiveRequestCount = 0 ;
-			}
-			LLCurl::getCurlThread()->killMulti(multi);
-			mMultiSet.erase(curiter) ;
-			continue ;
-		}
-
-		queued += multi->mQueued;
-		if (multi->getState() != LLCurl::Multi::STATE_READY)
-		{
-			++queued;
-		}
-	}
-	return queued;
-}
-
-LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) : 
-	LLCurlRequest(), 
-	mConcurrency(concurrency),
-	mInQueue(0),
-	mMutex(NULL),
-	mHandleCounter(1),
-	mTotalIssuedRequests(0),
-	mTotalReceivedBits(0)
-{
-	mGlobalTimer.reset();
-}
-
-LLCurlTextureRequest::~LLCurlTextureRequest()
-{
-	mRequestMap.clear();
-
-	for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
-	{
-		delete *iter;
-	}
-	mCachedRequests.clear();
-}
-
-//return 0: success
-// > 0: cached handle
-U32 LLCurlTextureRequest::getByteRange(const std::string& url,
-								 const headers_t& headers,
-								 S32 offset, S32 length, U32 pri,
-								 LLCurl::ResponderPtr responder, F32 delay_time)
-{
-	U32 ret_val = 0;
-	bool success = false;	
-
-	if(mInQueue < mConcurrency && delay_time < 0.f)
-	{
-		success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);		
-	}
-
-	LLMutexLock lock(&mMutex);
-
-	if(success)
-	{
-		mInQueue++;
-		mTotalIssuedRequests++;
-	}
-	else
-	{
-		request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
-		if(delay_time > 0.f)
-		{
-			request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
-		}
-
-		mCachedRequests.insert(request);
-		mRequestMap[mHandleCounter] = request;
-		ret_val = mHandleCounter;
-		mHandleCounter++;
-
-		if(!mHandleCounter)
-		{
-			mHandleCounter = 1;
-		}
-	}
-
-	return ret_val;
-}
-
-void LLCurlTextureRequest::completeRequest(S32 received_bytes)
-{
-	LLMutexLock lock(&mMutex);
-
-	llassert_always(mInQueue > 0);
-
-	mInQueue--;
-	mTotalReceivedBits += received_bytes * 8;
-}
-
-void LLCurlTextureRequest::nextRequests()
-{
-	if(mCachedRequests.empty() || mInQueue >= mConcurrency)
-	{
-		return;
-	}
-
-	F32 cur_time = mGlobalTimer.getElapsedTimeF32();
-
-	req_queue_t::iterator iter;	
-	{
-		LLMutexLock lock(&mMutex);
-		iter = mCachedRequests.begin();
-	}
-	while(1)
-	{
-		request_t* request = *iter;
-		if(request->mStartTime < cur_time)
-		{
-			if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
-			{
-				break;
-			}
-
-			LLMutexLock lock(&mMutex);
-			++iter;
-			mInQueue++;
-			mTotalIssuedRequests++;
-			mCachedRequests.erase(request);
-			mRequestMap.erase(request->mHandle);
-			delete request;
-
-			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
-			{
-				break;
-			}
-		}
-		else
-		{
-			LLMutexLock lock(&mMutex);
-			++iter;
-			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
-			{
-				break;
-			}
-		}
-	}
-
-	return;
-}
-
-void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
-{
-	if(!handle)
-	{
-		return;
-	}
-
-	LLMutexLock lock(&mMutex);
-
-	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
-	if(iter != mRequestMap.end())
-	{
-		request_t* req = iter->second;
-		
-		if(req->mPriority != pri)
-		{
-			mCachedRequests.erase(req);
-			req->mPriority = pri;
-			mCachedRequests.insert(req);
-		}
-	}
-}
-
-void LLCurlTextureRequest::removeRequest(U32 handle)
-{
-	if(!handle)
-	{
-		return;
-	}
-
-	LLMutexLock lock(&mMutex);
-
-	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
-	if(iter != mRequestMap.end())
-	{
-		request_t* req = iter->second;
-		mRequestMap.erase(iter);
-		mCachedRequests.erase(req);
-		delete req;
-	}
-}
-
-bool LLCurlTextureRequest::isWaiting(U32 handle)
-{
-	if(!handle)
-	{
-		return false;
-	}
-
-	LLMutexLock lock(&mMutex);
-	return mRequestMap.find(handle) != mRequestMap.end();
-}
-
-U32 LLCurlTextureRequest::getTotalReceivedBits()
-{
-	LLMutexLock lock(&mMutex);
-
-	U32 bits = mTotalReceivedBits;
-	mTotalReceivedBits = 0;
-	return bits;
-}
-
-U32 LLCurlTextureRequest::getTotalIssuedRequests()
-{
-	LLMutexLock lock(&mMutex);
-	return mTotalIssuedRequests;
-}
-
-S32 LLCurlTextureRequest::getNumRequests()
-{
-	LLMutexLock lock(&mMutex);
-	return mInQueue;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// For generating one easy request
-// associated with a single multi request
-
-LLCurlEasyRequest::LLCurlEasyRequest()
-	: mRequestSent(false),
-	  mResultReturned(false)
-{
-	mMulti = new LLCurl::Multi();
-	
-	if(mMulti->isValid())
-	{
-	mEasy = mMulti->allocEasy();
-	if (mEasy)
-	{
-		mEasy->setErrorBuffer();
-		mEasy->setCA();
-		// Set proxy settings if configured to do so.
-		LLProxy::getInstance()->applyProxySettings(mEasy);
-	}
-}
-	else
-	{
-		LLCurl::getCurlThread()->killMulti(mMulti) ;
-		mEasy = NULL ;
-		mMulti = NULL ;
-	}
-}
-
-LLCurlEasyRequest::~LLCurlEasyRequest()
-{
-	LLCurl::getCurlThread()->killMulti(mMulti) ;
-}
-	
-void LLCurlEasyRequest::setopt(CURLoption option, S32 value)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(option, value);
-	}
-}
-
-void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setoptString(option, value);
-	}
-}
-
-void LLCurlEasyRequest::setPost(char* postdata, S32 size)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(CURLOPT_POST, 1);
-		mEasy->setopt(CURLOPT_POSTFIELDS, postdata);
-		mEasy->setopt(CURLOPT_POSTFIELDSIZE, size);
-	}
-}
-
-void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback);
-		mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER
-	}
-}
-
-void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback);
-		mEasy->setopt(CURLOPT_WRITEDATA, userdata);
-	}
-}
-
-void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback);
-		mEasy->setopt(CURLOPT_READDATA, userdata);
-	}
-}
-
-void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback);
-		mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata);
-	}
-}
-
-void LLCurlEasyRequest::slist_append(const std::string& header, const std::string& value)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->slist_append(header, value);
-	}
-}
-
-void LLCurlEasyRequest::slist_append(const char* str)
-{
-	if (isValid() && mEasy)
-	{
-		mEasy->slist_append(str);
-	}
-}
-
-void LLCurlEasyRequest::sendRequest(const std::string& url)
-{
-	llassert_always(!mRequestSent);
-	mRequestSent = true;
-	LL_DEBUGS() << url << LL_ENDL;
-	if (isValid() && mEasy)
-	{
-		mEasy->setHeaders();
-		mEasy->setoptString(CURLOPT_URL, url);
-		mMulti->addEasy(mEasy);
-	}
-}
-
-void LLCurlEasyRequest::requestComplete()
-{
-	llassert_always(mRequestSent);
-	mRequestSent = false;
-	if (isValid() && mEasy)
-	{
-		mMulti->removeEasy(mEasy);
-	}
-}
-
-// Usage: Call getRestult until it returns false (no more messages)
-bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
-{
-	if(!isValid())
-	{
-		return false ;
-	}
-	if (!mMulti->isCompleted())
-	{ //we're busy, try again later
-		return false;
-	}
-	mMulti->setState(LLCurl::Multi::STATE_READY) ;
-
-	if (!mEasy)
-	{
-		// Special case - we failed to initialize a curl_easy (can happen if too many open files)
-		//  Act as though the request failed to connect
-		if (mResultReturned)
-		{
-			return false;
-		}
-		else
-		{
-			*result = CURLE_FAILED_INIT;
-			mResultReturned = true;
-			return true;
-		}
-	}
-	// In theory, info_read might return a message with a status other than CURLMSG_DONE
-	// In practice for all messages returned, msg == CURLMSG_DONE
-	// Ignore other messages just in case
-	while(1)
-	{
-		S32 q;
-		CURLMsg* curlmsg = info_read(&q, info);
-		if (curlmsg)
-		{
-			if (curlmsg->msg == CURLMSG_DONE)
-			{
-				*result = curlmsg->data.result;			
-				return true;
-			}
-			// else continue
-		}
-		else
-		{
-			return false;
-		}
-	}
-}
-
-// private
-CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info)
-{
-	if (mEasy)
-	{
-		CURLMsg* curlmsg = mMulti->info_read(q);
-		if (curlmsg && curlmsg->msg == CURLMSG_DONE)
-		{
-			if (info)
-			{
-				mEasy->getTransferInfo(info);
-			}
-		}
-		return curlmsg;
-	}
-	return NULL;
-}
-
-std::string LLCurlEasyRequest::getErrorString()
-{
-	return isValid() &&  mEasy ? std::string(mEasy->getErrorBuffer()) : std::string();
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-#if SAFE_SSL
-//static
-void LLCurl::ssl_locking_callback(int mode, int type, const char *file, int line)
-{
-	if (mode & CRYPTO_LOCK)
-	{
-		LLCurl::sSSLMutex[type]->lock();
-	}
-	else
-	{
-		LLCurl::sSSLMutex[type]->unlock();
-	}
-}
-
-//static
-unsigned long LLCurl::ssl_thread_id(void)
-{
-	return LLThread::currentID();
-}
-#endif
-
-void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded)
-{
-	sCurlRequestTimeOut = curl_reuest_timeout ; //seconds
-	sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined).
-
-	// Do not change this "unless you are familiar with and mean to control 
-	// internal operations of libcurl"
-	// - http://curl.haxx.se/libcurl/c/curl_global_init.html
-	CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
-
-	check_curl_code(code);
-	
-#if SAFE_SSL
-	S32 mutex_count = CRYPTO_num_locks();
-	for (S32 i=0; i<mutex_count; i++)
-	{
-		sSSLMutex.push_back(new LLMutex(NULL));
-	}
-	CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
-	CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);
-#endif
-
-	sCurlThread = new LLCurlThread(multi_threaded) ;
-	if(multi_threaded)
-	{
-		sHandleMutexp = new LLMutex(NULL) ;
-		Easy::sHandleMutexp = new LLMutex(NULL) ;
-	}
-}
-
-void LLCurl::cleanupClass()
-{
-	sNotQuitting = false; //set quitting
-
-	//shut down curl thread
-	while(1)
-	{
-		if(!sCurlThread->update(1)) //finish all tasks
-		{
-			break ;
-		}
-	}
-	LL_CHECK_MEMORY
-	sCurlThread->shutdown() ;
-	LL_CHECK_MEMORY
-	delete sCurlThread ;
-	sCurlThread = NULL ;
-	LL_CHECK_MEMORY
-
-#if SAFE_SSL
-	CRYPTO_set_locking_callback(NULL);
-	for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer());
-	sSSLMutex.clear();
-#endif
-	
-	LL_CHECK_MEMORY
-	Easy::deleteAllFreeHandles();
-	LL_CHECK_MEMORY
-	Easy::deleteAllActiveHandles();
-	LL_CHECK_MEMORY
-
-	// Free the template easy handle
-	curl_easy_cleanup(sCurlTemplateStandardHandle);
-	sCurlTemplateStandardHandle = NULL;
-	LL_CHECK_MEMORY
-
-	delete Easy::sHandleMutexp ;
-	Easy::sHandleMutexp = NULL ;
-
-	LL_CHECK_MEMORY
-
-	delete sHandleMutexp ;
-	sHandleMutexp = NULL ;
-
-	LL_CHECK_MEMORY
-
-	// removed as per https://jira.secondlife.com/browse/SH-3115
-	//llassert(Easy::sActiveHandles.empty());
-}
-
-//static 
-CURLM* LLCurl::newMultiHandle()
-{
-	llassert(sNotQuitting);
-
-	LLMutexLock lock(sHandleMutexp) ;
-
-	if(sTotalHandles + 1 > sMaxHandles)
-	{
-		LL_WARNS() << "no more handles available." << LL_ENDL ;
-		return NULL ; //failed
-	}
-	sTotalHandles++;
-
-	CURLM* ret = curl_multi_init() ;
-	if(!ret)
-	{
-		LL_WARNS() << "curl_multi_init failed." << LL_ENDL ;
-	}
-
-	return ret ;
-}
-
-//static 
-CURLMcode  LLCurl::deleteMultiHandle(CURLM* handle)
-{
-	if(handle)
-	{
-		LLMutexLock lock(sHandleMutexp) ;		
-		sTotalHandles-- ;
-		return curl_multi_cleanup(handle) ;
-	}
-	return CURLM_OK ;
-}
-
-//static 
-CURL*  LLCurl::newEasyHandle()
-{
-	llassert(sNotQuitting);
-	LLMutexLock lock(sHandleMutexp) ;
-
-	if(sTotalHandles + 1 > sMaxHandles)
-	{
-		LL_WARNS() << "no more handles available." << LL_ENDL ;
-		return NULL ; //failed
-	}
-	sTotalHandles++;
-
-	CURL* ret = createStandardCurlHandle();
-	if(!ret)
-	{
-		LL_WARNS() << "failed to create curl handle." << LL_ENDL ;
-	}
-
-	return ret ;
-}
-
-//static 
-void  LLCurl::deleteEasyHandle(CURL* handle)
-{
-	if(handle)
-	{
-		LLMutexLock lock(sHandleMutexp) ;
-		LL_CHECK_MEMORY
-		curl_easy_cleanup(handle) ;
-		LL_CHECK_MEMORY
-		sTotalHandles-- ;
-	}
-}
-
-const unsigned int LLCurl::MAX_REDIRECTS = 5;
-
-// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
-void LLCurlFF::check_easy_code(CURLcode code)
-{
-	check_curl_code(code);
-}
-void LLCurlFF::check_multi_code(CURLMcode code)
-{
-	check_curl_multi_code(code);
-}
-
-
-// Static
-CURL* LLCurl::createStandardCurlHandle()
-{
-	if (sCurlTemplateStandardHandle == NULL)
-	{	// Late creation of the template curl handle
-		sCurlTemplateStandardHandle = curl_easy_init();
-		if (sCurlTemplateStandardHandle == NULL)
-		{
-			LL_WARNS() << "curl error calling curl_easy_init()" << LL_ENDL;
-		}
-		else
-		{
-			CURLcode result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOSIGNAL, 1);
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOPROGRESS, 1);
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_ENCODING, "");	
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_AUTOREFERER, 1);
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_FOLLOWLOCATION, 1);	
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYPEER, 1);
-			check_curl_code(result);
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYHOST, 0);
-			check_curl_code(result);
-
-			// The Linksys WRT54G V5 router has an issue with frequent
-			// DNS lookups from LAN machines.  If they happen too often,
-			// like for every HTTP request, the router gets annoyed after
-			// about 700 or so requests and starts issuing TCP RSTs to
-			// new connections.  Reuse the DNS lookups for even a few
-			// seconds and no RSTs.
-			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
-			check_curl_code(result);
-		}
-	}
-
-	return curl_easy_duphandle(sCurlTemplateStandardHandle);
-}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
deleted file mode 100755
index 385d9fffa8990beb1f07dad83e994eb2ccd53b7d..0000000000000000000000000000000000000000
--- a/indra/llmessage/llcurl.h
+++ /dev/null
@@ -1,556 +0,0 @@
-/** 
- * @file llcurl.h
- * @author Zero / Donovan
- * @date 2006-10-15
- * @brief A wrapper around libcurl.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
- 
-#ifndef LL_LLCURL_H
-#define LL_LLCURL_H
-
-#include "linden_common.h"
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <boost/intrusive_ptr.hpp>
-#include <curl/curl.h> // TODO: remove dependency
-
-#include "llbuffer.h"
-#include "llhttpconstants.h"
-#include "lliopipe.h"
-#include "llsd.h"
-#include "llqueuedthread.h"
-#include "llframetimer.h"
-#include "llpointer.h"
-#include "llsingleton.h"
-
-class LLMutex;
-class LLCurlThread;
-
-// For whatever reason, this is not typedef'd in curl.h
-typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream);
-
-class LLCurl
-{
-	LOG_CLASS(LLCurl);
-	
-public:
-	class Easy;
-	class Multi;
-
-	struct TransferInfo
-	{
-		TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {}
-		F64 mSizeDownload;
-		F64 mTotalTime;
-		F64 mSpeedDownload;
-	};
-	
-	class Responder : public LLThreadSafeRefCount
-	{
-	//LOG_CLASS(Responder);
-	public:
-
-		Responder();
-		virtual ~Responder();
-
-		virtual bool followRedir() 
-		{
-			return false;
-		}
-
-		/**
-		 * @brief return true if the status code indicates success.
-		 */
-		bool isGoodStatus() const { return isHttpGoodStatus(mStatus); }
-
-		S32 getStatus() const { return mStatus; }
-		const std::string& getReason() const { return mReason; }
-		const LLSD& getContent() const { return mContent; }
-		bool hasResponseHeader(const std::string& header) const;
-		const std::string& getResponseHeader(const std::string& header) const;
-		const LLSD& getResponseHeaders() const { return mResponseHeaders; }
-		const std::string& getURL() const { return mURL; }
-		EHTTPMethod getHTTPMethod() const { return mHTTPMethod; }
-
-		// This formats response information for use in log spam.  Includes content spam.
-		std::string dumpResponse() const;
-
-		// Allows direct triggering of success/error with different results.
-		void completeResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
-		void successResult(const LLSD& content);
-		void failureResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
-
-		// The default implementation will try to parse body content as an LLSD, however
-		// it should not spam about parsing failures unless the server sent a
-		// Content-Type: application/llsd+xml header.
-		virtual void completedRaw(
-			const LLChannelDescriptors& channels,
-			const LLIOPipe::buffer_ptr_t& buffer);
-			/**< Override point for clients that may want to use this
-			   class when the response is some other format besides LLSD
-			*/
-			
-
-		// The http* methods are not public since these should be triggered internally
-		// after status, reason, content, etc have been set.
-		// If you need to trigger a completion method, use the *Result methods, above.
-	protected:
-		// These methods are the preferred way to process final results.
-		// By default, when one of these is called the following information will be resolved:
-		// * HTTP status code - getStatus()
-		// * Reason string - getReason()
-		// * Content - getContent()
-		// * Response Headers - getResponseHeaders()
-
-		// By default, httpSuccess is triggered whenever httpCompleted is called with a 2xx status code.
-		virtual void httpSuccess();
-			//< called by completed for good status codes.
-
-		// By default, httpFailure is triggered whenever httpCompleted is called with a non-2xx status code.
-		virtual void httpFailure();
-			//< called by httpCompleted() on bad status 
-
-		// httpCompleted does not generally need to be overridden, unless
-		// you don't care about the status code (which determine httpFailure or httpSuccess)
-		// or if you want to re-interpret what a 'good' vs' bad' status code is.
-		virtual void httpCompleted();
-			/**< The default implementation calls
-				either:
-				* httpSuccess(), or
-				* httpFailure() 
-			*/
-
-	public:
-		void setHTTPMethod(EHTTPMethod method);
-		void setURL(const std::string& url);
-		void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
-		void setResponseHeader(const std::string& header, const std::string& value);
-
-	private:
-		// These can be accessed by the get* methods.  Treated as 'read-only' during completion handlers.
-		EHTTPMethod mHTTPMethod;
-		std::string mURL;
-		LLSD mResponseHeaders;
-
-	protected:
-		// These should also generally be treated as 'read-only' during completion handlers
-		// and should be accessed by the get* methods.  The exception to this rule would
-		// be when overriding the completedRaw method in preparation for calling httpCompleted().
-		S32 mStatus;
-		std::string mReason;
-		LLSD mContent;
-	};
-	typedef LLPointer<Responder>	ResponderPtr;
-
-
-	/**
-	 * @ brief Set certificate authority file used to verify HTTPS certs.
-	 */
-	static void setCAFile(const std::string& file);
-
-	/**
-	 * @ brief Set certificate authority path used to verify HTTPS certs.
-	 */
-	static void setCAPath(const std::string& path);
-
-	/**
-	 * @ brief Return human-readable string describing libcurl version.
-	 */
-	static std::string getVersionString();
-	
-	/**
-	 * @ brief Get certificate authority file used to verify HTTPS certs.
-	 */
-	static const std::string& getCAFile() { return sCAFile; }
-
-	/**
-	 * @ brief Get certificate authority path used to verify HTTPS certs.
-	 */
-	static const std::string& getCAPath() { return sCAPath; }
-
-	/**
-	 * @ brief Initialize LLCurl class
-	 */
-	static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false);
-
-	/**
-	 * @ brief Cleanup LLCurl class
-	 */
-	static void cleanupClass();
-
-	/**
-	 * @ brief curl error code -> string
-	 */
-	static std::string strerror(CURLcode errorcode);
-	
-	// For OpenSSL callbacks
-	static std::vector<LLMutex*> sSSLMutex;
-
-	// OpenSSL callbacks
-	static void ssl_locking_callback(int mode, int type, const char *file, int line);
-	static unsigned long ssl_thread_id(void);
-
-	static LLCurlThread* getCurlThread() { return sCurlThread ;}
-
-	static CURLM* newMultiHandle() ;
-	static CURLMcode deleteMultiHandle(CURLM* handle) ;
-	static CURL*  newEasyHandle() ;
-	static void   deleteEasyHandle(CURL* handle) ;
-
-	static CURL*	createStandardCurlHandle();
-
-private:
-	static std::string sCAPath;
-	static std::string sCAFile;
-	static const unsigned int MAX_REDIRECTS;
-	static LLCurlThread* sCurlThread;
-
-	static LLMutex* sHandleMutexp ;
-	static S32      sTotalHandles ;
-	static S32      sMaxHandles;
-	static CURL*	sCurlTemplateStandardHandle;
-public:
-	static bool     sNotQuitting;
-	static F32      sCurlRequestTimeOut;	
-};
-
-class LLCurl::Easy
-{
-	LOG_CLASS(Easy);
-
-private:
-	Easy();
-
-public:
-	static Easy* getEasy();
-	~Easy();
-
-	CURL* getCurlHandle() const { return mCurlEasyHandle; }
-
-	void setErrorBuffer();
-	void setCA();
-
-	void setopt(CURLoption option, S32 value);
-	// These assume the setter does not free value!
-	void setopt(CURLoption option, void* value);
-	void setopt(CURLoption option, char* value);
-	// Copies the string so that it is guaranteed to stick around
-	void setoptString(CURLoption option, const std::string& value);
-
-	void slist_append(const std::string& header, const std::string& value);
-	void slist_append(const char* str);
-	void setHeaders();
-
-	S32 report(CURLcode);
-	void getTransferInfo(LLCurl::TransferInfo* info);
-
-	void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
-
-	const char* getErrorBuffer();
-
-	std::stringstream& getInput() { return mInput; }
-	std::stringstream& getHeaderOutput() { return mHeaderOutput; }
-	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; }
-	const LLChannelDescriptors& getChannels() { return mChannels; }
-
-	void resetState();
-
-	static CURL* allocEasyHandle();
-	static void releaseEasyHandle(CURL* handle);
-
-private:
-	friend class LLCurl;
-	friend class LLCurl::Multi;
-
-	CURL*				mCurlEasyHandle;
-	struct curl_slist*	mHeaders;
-
-	std::stringstream	mRequest;
-	LLChannelDescriptors mChannels;
-	LLIOPipe::buffer_ptr_t mOutput;
-	std::stringstream	mInput;
-	std::stringstream	mHeaderOutput;
-	char				mErrorBuffer[CURL_ERROR_SIZE];
-
-	// Note: char*'s not strings since we pass pointers to curl
-	std::vector<char*>	mStrings;
-
-	LLCurl::ResponderPtr		mResponder;
-
-	static std::set<CURL*> sFreeHandles;
-	static std::set<CURL*> sActiveHandles;
-	static LLMutex*        sHandleMutexp ;
-
-	static void deleteAllActiveHandles();
-	static void deleteAllFreeHandles();
-};
-
-class LLCurl::Multi
-{
-	LOG_CLASS(Multi);
-
-	friend class LLCurlThread ;
-
-private:
-	~Multi();
-
-	void markDead() ;
-	bool doPerform();
-
-public:
-
-	typedef enum
-	{
-		STATE_READY=0,
-		STATE_PERFORMING=1,
-		STATE_COMPLETED=2
-	} ePerformState;
-
-	Multi(F32 idle_time_out = 0.f);	
-
-	LLCurl::Easy* allocEasy();
-	bool addEasy(LLCurl::Easy* easy);	
-	void removeEasy(LLCurl::Easy* easy);
-	
-	void lock() ;
-	void unlock() ;
-
-	void setState(ePerformState state) ;
-	ePerformState getState() ;
-	
-	bool isCompleted() ;
-	bool isValid() {return mCurlMultiHandle != NULL && mValid;}
-	bool isDead() {return mDead;}
-
-	bool waitToComplete() ;
-
-	S32 process();
-	
-	CURLMsg* info_read(S32* msgs_in_queue);
-
-	S32 mQueued;
-	S32 mErrorCount;
-	
-private:
-	void easyFree(LLCurl::Easy*);
-	void cleanup(bool deleted = false) ;
-	
-	CURLM* mCurlMultiHandle;
-
-	typedef std::set<LLCurl::Easy*> easy_active_list_t;
-	easy_active_list_t mEasyActiveList;
-	typedef std::map<CURL*, LLCurl::Easy*> easy_active_map_t;
-	easy_active_map_t mEasyActiveMap;
-	typedef std::set<LLCurl::Easy*> easy_free_list_t;
-	easy_free_list_t mEasyFreeList;
-
-	LLQueuedThread::handle_t mHandle ;
-	ePerformState mState;
-
-	BOOL mDead ;
-	BOOL mValid ;
-	LLMutex* mMutexp ;
-	LLMutex* mDeletionMutexp ;
-	LLMutex* mEasyMutexp ;
-	LLFrameTimer mIdleTimer ;
-	F32 mIdleTimeOut;
-};
-
-class LLCurlThread : public LLQueuedThread
-{
-public:
-
-	class CurlRequest : public LLQueuedThread::QueuedRequest
-	{
-	protected:
-		virtual ~CurlRequest(); // use deleteRequest()
-		
-	public:
-		CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread);
-
-		/*virtual*/ bool processRequest();
-		/*virtual*/ void finishRequest(bool completed);
-
-	private:
-		// input
-		LLCurl::Multi* mMulti;
-		LLCurlThread*  mCurlThread;
-	};
-	friend class CurlRequest;
-
-public:
-	LLCurlThread(bool threaded = true) ;
-	virtual ~LLCurlThread() ;
-
-	S32 update(F32 max_time_ms);
-
-	void addMulti(LLCurl::Multi* multi) ;
-	void killMulti(LLCurl::Multi* multi) ;
-
-private:
-	bool doMultiPerform(LLCurl::Multi* multi) ;
-	void deleteMulti(LLCurl::Multi* multi) ;
-	void cleanupMulti(LLCurl::Multi* multi) ;
-} ;
-
-
-class LLCurlRequest
-{
-public:
-	typedef std::vector<std::string> headers_t;
-	
-	LLCurlRequest();
-	~LLCurlRequest();
-
-	void get(const std::string& url, LLCurl::ResponderPtr responder);
-	bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
-	bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
-	bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0);
-	
-	S32  process();
-	S32  getQueued();
-
-private:
-	void addMulti();
-	LLCurl::Easy* allocEasy();
-	bool addEasy(LLCurl::Easy* easy);
-	
-private:
-	typedef std::set<LLCurl::Multi*> curlmulti_set_t;
-	curlmulti_set_t mMultiSet;
-	LLCurl::Multi* mActiveMulti;
-	S32 mActiveRequestCount;
-	BOOL mProcessing;
-};
-
-//for texture fetch only
-class LLCurlTextureRequest : public LLCurlRequest
-{
-public:
-	LLCurlTextureRequest(S32 concurrency);
-	~LLCurlTextureRequest();
-
-	U32 getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder, F32 delay_time = -1.f);
-	void nextRequests();
-	void completeRequest(S32 received_bytes);
-
-	void updatePriority(U32 handle, U32 pri);
-	void removeRequest(U32 handle);
-
-	U32 getTotalReceivedBits();
-	U32 getTotalIssuedRequests();
-	S32 getNumRequests();
-	bool isWaiting(U32 handle);
-	
-private:
-	LLMutex mMutex;
-	S32 mConcurrency;
-	S32 mInQueue; //request currently in queue.
-	U32 mHandleCounter;
-	U32 mTotalIssuedRequests;
-	U32 mTotalReceivedBits;
-
-	typedef struct _request_t
-	{
-		_request_t(U32 handle, const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder) :
-				mHandle(handle), mUrl(url), mHeaders(headers), mOffset(offset), mLength(length), mPriority(pri), mResponder(responder), mStartTime(0.f)
-				{}
-
-		U32  mHandle;
-		std::string mUrl;
-		LLCurlRequest::headers_t mHeaders;
-		S32 mOffset;
-		S32 mLength;
-		LLCurl::ResponderPtr mResponder;
-		U32 mPriority;
-		F32 mStartTime; //start time to issue this request
-	} request_t;
-
-	struct request_compare
-	{
-		bool operator()(const request_t* lhs, const request_t* rhs) const
-		{
-			if(lhs->mPriority != rhs->mPriority)
-			{
-				return lhs->mPriority > rhs->mPriority; // higher priority in front of queue (set)
-			}
-			else
-			{
-				return (U32)lhs < (U32)rhs;
-			}
-		}
-	};
-
-	typedef std::set<request_t*, request_compare> req_queue_t;
-	req_queue_t mCachedRequests;
-	std::map<S32, request_t*> mRequestMap;
-
-	LLFrameTimer mGlobalTimer;
-};
-
-class LLCurlEasyRequest
-{
-public:
-	LLCurlEasyRequest();
-	~LLCurlEasyRequest();
-	void setopt(CURLoption option, S32 value);
-	void setoptString(CURLoption option, const std::string& value);
-	void setPost(char* postdata, S32 size);
-	void setHeaderCallback(curl_header_callback callback, void* userdata);
-	void setWriteCallback(curl_write_callback callback, void* userdata);
-	void setReadCallback(curl_read_callback callback, void* userdata);
-	void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
-	void slist_append(const std::string& header, const std::string& value);
-	void slist_append(const char* str);
-	void sendRequest(const std::string& url);
-	void requestComplete();
-	bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
-	std::string getErrorString();
-	bool isCompleted() {return mMulti->isCompleted() ;}
-	bool wait() { return mMulti->waitToComplete(); }
-	bool isValid() {return mMulti && mMulti->isValid(); }
-
-	LLCurl::Easy* getEasy() const { return mEasy; }
-
-private:
-	CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info);
-	
-private:
-	LLCurl::Multi* mMulti;
-	LLCurl::Easy* mEasy;
-	bool mRequestSent;
-	bool mResultReturned;
-};
-
-// Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace.
-namespace LLCurlFF
-{
-	void check_easy_code(CURLcode code);
-	void check_multi_code(CURLMcode code);
-}
-
-#endif // LL_LLCURL_H
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index 52b60a176e45c7fb19f634c47fa842a29db58f2a..92fcd38d3b36ffe1f92fb8453e69f596649ed3f5 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -26,616 +26,989 @@
 #include "llexperiencecache.h"
 
 #include "llavatarname.h"
-#include "llframetimer.h"
-#include "llhttpclient.h"
 #include "llsdserialize.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "lleventfilter.h"
+#include "llcoproceduremanager.h"
+#include "lldir.h"
 #include <set>
 #include <map>
-#include "boost/tokenizer.hpp"
+#include <boost/tokenizer.hpp>
+#include <boost/concept_check.hpp>
 
-
-namespace LLExperienceCache
+//=========================================================================
+namespace LLExperienceCacheImpl
 {
+	void mapKeys(const LLSD& legacyKeys);
+    F64 getErrorRetryDeltaTime(S32 status, LLSD headers);
+    bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age);
+
+    static const std::string PRIVATE_KEY    = "private_id";
+    static const std::string EXPERIENCE_ID  = "public_id";
+
+    static const std::string MAX_AGE("max-age");
+    static const boost::char_separator<char> EQUALS_SEPARATOR("=");
+    static const boost::char_separator<char> COMMA_SEPARATOR(",");
 
+    // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used.
     typedef std::map<LLUUID, LLUUID> KeyMap;
     KeyMap privateToPublicKeyMap;
+}
 
-    void mapKeys(const LLSD& legacyKeys);
+//=========================================================================
+const std::string LLExperienceCache::PRIVATE_KEY	= "private_id";
+const std::string LLExperienceCache::MISSING       	= "DoesNotExist";
+
+const std::string LLExperienceCache::AGENT_ID      = "agent_id";
+const std::string LLExperienceCache::GROUP_ID      = "group_id";
+const std::string LLExperienceCache::EXPERIENCE_ID	= "public_id";
+const std::string LLExperienceCache::NAME			= "name";
+const std::string LLExperienceCache::PROPERTIES		= "properties";
+const std::string LLExperienceCache::EXPIRES		= "expiration";  
+const std::string LLExperienceCache::DESCRIPTION	= "description";
+const std::string LLExperienceCache::QUOTA         	= "quota";
+const std::string LLExperienceCache::MATURITY      = "maturity";
+const std::string LLExperienceCache::METADATA      = "extended_metadata";
+const std::string LLExperienceCache::SLURL         	= "slurl";
+
+// should be in sync with experience-api/experiences/models.py
+const int LLExperienceCache::PROPERTY_INVALID		= 1 << 0;
+const int LLExperienceCache::PROPERTY_PRIVILEGED	= 1 << 3;
+const int LLExperienceCache::PROPERTY_GRID			= 1 << 4;
+const int LLExperienceCache::PROPERTY_PRIVATE		= 1 << 5;
+const int LLExperienceCache::PROPERTY_DISABLED	= 1 << 6;  
+const int LLExperienceCache::PROPERTY_SUSPENDED	= 1 << 7;
+
+// default values
+const F64 LLExperienceCache::DEFAULT_EXPIRATION	= 600.0;
+const S32 LLExperienceCache::DEFAULT_QUOTA			= 128; // this is megabytes
+const int LLExperienceCache::SEARCH_PAGE_SIZE     = 30;
+
+//=========================================================================
+LLExperienceCache::LLExperienceCache():
+    mShutdown(false)
+{
+}
 
-	std::string sLookupURL;
+LLExperienceCache::~LLExperienceCache()
+{
 
-	typedef std::map<LLUUID, std::string> ask_queue_t;
-	ask_queue_t sAskQueue;
+}
 
-	typedef std::map<LLUUID, F64> pending_queue_t;
-	pending_queue_t sPendingQueue;
+void LLExperienceCache::initSingleton()
+{
+    mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
 
-	cache_t sCache;
-	int sMaximumLookups = 10;
+    LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL;
+    llifstream cache_stream(mCacheFileName.c_str());
 
-	LLFrameTimer sRequestTimer;
+    if (cache_stream.is_open())
+    {
+        cache_stream >> (*this);
+    }
 
-	// Periodically clean out expired entries from the cache
-	LLFrameTimer sEraseExpiredTimer;
+    LLCoros::instance().launch("LLExperienceCache::idleCoro",
+        boost::bind(&LLExperienceCache::idleCoro, this));
 
-	// May have multiple callbacks for a single ID, which are
-	// represented as multiple slots bound to the signal.
-	// Avoid copying signals via pointers.
-	typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
-	signal_map_t sSignalMap;
+}
 
+void LLExperienceCache::cleanup()
+{
+    LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL;
+
+    llofstream cache_stream(mCacheFileName.c_str());
+    if (cache_stream.is_open())
+    {
+        cache_stream << (*this);
+    }
+    mShutdown = true;
+}
 
+//-------------------------------------------------------------------------
+void LLExperienceCache::importFile(std::istream& istr)
+{
+    LLSD data;
+    S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
+    if (parse_count < 1) return;
 
-	bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
-	void eraseExpired();
+    LLSD experiences = data["experiences"];
 
-	void processExperience( const LLUUID& public_key, const LLSD& experience ) 
-	{
-		sCache[public_key]=experience;
-		LLSD & row = sCache[public_key];
+    LLUUID public_key;
+    LLSD::map_const_iterator it = experiences.beginMap();
+    for (; it != experiences.endMap(); ++it)
+    {
+        public_key.set(it->first);
+        mCache[public_key] = it->second;
+    }
 
-		if(row.has(EXPIRES))
-		{
-			row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
-		}
+    LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL;
+}
 
-		if(row.has(EXPERIENCE_ID))
-		{
-			sPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
-		}
+void LLExperienceCache::exportFile(std::ostream& ostr) const
+{
+    LLSD experiences;
 
-		//signal
-		signal_map_t::iterator sig_it =	sSignalMap.find(public_key);
-		if (sig_it != sSignalMap.end())
-		{
-			callback_signal_t* signal = sig_it->second;
-			(*signal)(experience);
+    cache_t::const_iterator it = mCache.begin();
+    for (; it != mCache.end(); ++it)
+    {
+        if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() ||
+            it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID))
+            continue;
 
-			sSignalMap.erase(public_key);
+        experiences[it->first.asString()] = it->second;
+    }
 
-			delete signal;
-		}
-	}
+    LLSD data;
+    data["experiences"] = experiences;
 
-	void initClass( )
-	{
-	}
+    LLSDSerialize::toPrettyXML(data, ostr);
+}
+
+// *TODO$: Rider: This method does not seem to be used... it may be useful in testing.
+void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)
+{
+	LLExperienceCacheImpl::mapKeys(legacyKeys);
+    LLSD::array_const_iterator it = legacyKeys.beginArray();
+    for (/**/; it != legacyKeys.endArray(); ++it)
+    {
+        LLSD experience = *it;
+        if (experience.has(EXPERIENCE_ID))
+        {
+            if (!experience.has(EXPIRES))
+            {
+                experience[EXPIRES] = initialExpiration;
+            }
+            processExperience(experience[EXPERIENCE_ID].asUUID(), experience);
+        }
+        else
+        {
+            LL_WARNS("ExperienceCache")
+                << "Skipping bootstrap entry which is missing " << EXPERIENCE_ID
+                << LL_ENDL;
+        }
+    }
+}
+
+LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found)
+{
+    if (private_key.isNull())
+        return LLUUID::null;
+
+    LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key);
+    if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end())
+    {
+        if (null_if_not_found)
+        {
+            return LLUUID::null;
+        }
+        return private_key;
+    }
+    LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL;
+    return it->second;
+}
 
-	const cache_t& getCached()
+//=========================================================================
+void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience)
+{
+    LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL;
+
+	mCache[public_key]=experience;
+	LLSD & row = mCache[public_key];
+
+	if(row.has(EXPIRES))
 	{
-		return sCache;
+		row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
 	}
 
-	void setMaximumLookups( int maximumLookups)
+	if(row.has(EXPERIENCE_ID))
 	{
-		sMaximumLookups = maximumLookups;
+		mPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
 	}
 
-	void bootstrap(const LLSD& legacyKeys, int initialExpiration)
+	//signal
+	signal_map_t::iterator sig_it =	mSignalMap.find(public_key);
+	if (sig_it != mSignalMap.end())
 	{
-        mapKeys(legacyKeys);
-		LLSD::array_const_iterator it = legacyKeys.beginArray();
-		for(/**/; it != legacyKeys.endArray(); ++it)
-		{
-			LLSD experience = *it;
-			if(experience.has(EXPERIENCE_ID))
-			{
-				if(!experience.has(EXPIRES))
-				{
-					experience[EXPIRES] = initialExpiration;
-				}
-				processExperience(experience[EXPERIENCE_ID].asUUID(), experience);
-			}
-			else
-			{
-				LL_WARNS("ExperienceCache") 
-					<< "Skipping bootstrap entry which is missing " << EXPERIENCE_ID 
-					<< LL_ENDL;
-			}
-		}		
+		signal_ptr signal = sig_it->second;
+		(*signal)(experience);
+
+		mSignalMap.erase(public_key);
 	}
+}
+
+const LLExperienceCache::cache_t& LLExperienceCache::getCached()
+{
+	return mCache;
+}
 
+void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+    //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+        
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        F64 now = LLFrameTimer::getTotalSeconds();
+
+        LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+        // build dummy entries for the failed requests
+        for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it)
+        {
+            LLSD exp = get(*it);
+            //leave the properties alone if we already have a cache entry for this xp
+            if (exp.isUndefined())
+            {
+                exp[PROPERTIES] = PROPERTY_INVALID;
+            }
+            exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers);
+            exp[EXPERIENCE_ID] = *it;
+            exp["key_type"] = EXPERIENCE_ID;
+            exp["uuid"] = *it;
+            exp["error"] = (LLSD::Integer)status.getType();
+            exp[QUOTA] = DEFAULT_QUOTA;
+
+            processExperience(*it, exp);
+        }
+        return;
+    }
+
+    LLSD experiences = result["experience_keys"];
+    
+    for (LLSD::array_const_iterator it = experiences.beginArray(); 
+        it != experiences.endArray(); ++it)
+    {
+        const LLSD& row = *it;
+        LLUUID public_key = row[EXPERIENCE_ID].asUUID();
+
+        LL_DEBUGS("ExperienceCache") << "Received result for " << public_key
+            << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL;
+
+        processExperience(public_key, row);
+    }
+
+    LLSD error_ids = result["error_ids"];
+    
+    for (LLSD::array_const_iterator errIt = error_ids.beginArray(); 
+        errIt != error_ids.endArray(); ++errIt)
+    {
+        LLUUID id = errIt->asUUID();
+        LLSD exp;
+        exp[EXPIRES] = DEFAULT_EXPIRATION;
+        exp[EXPERIENCE_ID] = id;
+        exp[PROPERTIES] = PROPERTY_INVALID;
+        exp[MISSING] = true;
+        exp[QUOTA] = DEFAULT_QUOTA;
+
+        processExperience(id, exp);
+        LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL;
+    }
 
+}
 
-	bool expirationFromCacheControl(LLSD headers, F64 *expires)
+
+void LLExperienceCache::requestExperiences()
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string urlBase = mCapability("GetExperienceInfo");
+    if (urlBase.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Experience capability." << LL_ENDL;
+        return;
+    }
+
+    if (*urlBase.rbegin() != '/')
+    {
+        urlBase += "/";
+    }
+    urlBase += "id/";
+
+
+	F64 now = LLFrameTimer::getTotalSeconds();
+
+    const U32 EXP_URL_SEND_THRESHOLD = 3000;
+    const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH;
+
+    std::ostringstream ostr;
+    ostr << urlBase << "?page_size=" << PAGE_SIZE;
+    RequestQueue_t  requests;
+
+    while (!mRequestQueue.empty())
+    {
+        RequestQueue_t::iterator it = mRequestQueue.begin();
+        LLUUID key = (*it);
+        mRequestQueue.erase(it);
+        requests.insert(key);
+
+        ostr << "&" << EXPERIENCE_ID << "=" << key.asString();
+        mPendingQueue[key] = now;
+        
+        if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD))
+        {   // request is placed in the coprocedure pool for the ExpCache cache.  Throttling is done by the pool itself.
+            LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "RequestExperiences",
+                boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) );
+
+            ostr.str(std::string());
+            ostr << urlBase << "?page_size=" << PAGE_SIZE;
+            requests.clear();
+        }
+    }
+
+}
+
+
+bool LLExperienceCache::isRequestPending(const LLUUID& public_key)
+{
+	bool isPending = false;
+	const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+
+    PendingQueue_t::const_iterator it = mPendingQueue.find(public_key);
+
+	if(it != mPendingQueue.end())
 	{
-		// Allow the header to override the default
-		LLSD cache_control_header = headers["cache-control"];
-		if (cache_control_header.isDefined())
-		{
-			S32 max_age = 0;
-			std::string cache_control = cache_control_header.asString();
-			if (max_age_from_cache_control(cache_control, &max_age))
-			{
-				LL_WARNS("ExperienceCache") 
-					<< "got EXPIRES from headers, max_age " << max_age 
-					<< LL_ENDL;
-				F64 now = LLFrameTimer::getTotalSeconds();
-				*expires = now + (F64)max_age;
-				return true;
-			}
-		}
-		return false;
+		F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
+		isPending = (it->second > expire_time);
 	}
 
+	return isPending;
+}
+
+void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn)
+{
+    mCapability = queryfn;
+}
+
+
+void LLExperienceCache::idleCoro()
+{
+    const F32 SECS_BETWEEN_REQUESTS = 0.5f;
+    const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
+
+    LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL;
+    LLEventTimeout timeout;
+
+    do 
+    {
+        timeout.eventAfter(SECS_BETWEEN_REQUESTS, LLSD());
+        llcoro::suspendUntilEventOn(timeout);
+
+        if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
+        {
+            eraseExpired();
+        }
+
+        if (!mRequestQueue.empty())
+        {
+            requestExperiences();
+        }
 
-	static const std::string MAX_AGE("max-age");
-	static const boost::char_separator<char> EQUALS_SEPARATOR("=");
-	static const boost::char_separator<char> COMMA_SEPARATOR(",");
+    } while (!mShutdown);
 
-	bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
+    // The coroutine system will likely be shut down by the time we get to this point
+    // (or at least no further cycling will occur on it since the user has decided to quit.)
+}
+
+void LLExperienceCache::erase(const LLUUID& key)
+{
+	cache_t::iterator it = mCache.find(key);
+				
+	if(it != mCache.end())
 	{
-		// Split the string on "," to get a list of directives
-		typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-		tokenizer directives(cache_control, COMMA_SEPARATOR);
+		mCache.erase(it);
+	}
+}
 
-		tokenizer::iterator token_it = directives.begin();
-		for ( ; token_it != directives.end(); ++token_it)
-		{
-			// Tokens may have leading or trailing whitespace
-			std::string token = *token_it;
-			LLStringUtil::trim(token);
+void LLExperienceCache::eraseExpired()
+{
+	F64 now = LLFrameTimer::getTotalSeconds();
+	cache_t::iterator it = mCache.begin();
+	while (it != mCache.end())
+	{
+		cache_t::iterator cur = it;
+		LLSD& exp = cur->second;
+		++it;
+
+        //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL;
 
-			if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+		if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
+		{
+            if(!exp.has(EXPERIENCE_ID))
 			{
-				// ...this token starts with max-age, so let's chop it up by "="
-				tokenizer subtokens(token, EQUALS_SEPARATOR);
-				tokenizer::iterator subtoken_it = subtokens.begin();
-
-				// Must have a token
-				if (subtoken_it == subtokens.end()) return false;
-				std::string subtoken = *subtoken_it;
-
-				// Must exactly equal "max-age"
-				LLStringUtil::trim(subtoken);
-				if (subtoken != MAX_AGE) return false;
-
-				// Must have another token
-				++subtoken_it;
-				if (subtoken_it == subtokens.end()) return false;
-				subtoken = *subtoken_it;
-
-				// Must be a valid integer
-				// *NOTE: atoi() returns 0 for invalid values, so we have to
-				// check the string first.
-				// *TODO: Do servers ever send "0000" for zero?  We don't handle it
-				LLStringUtil::trim(subtoken);
-				if (subtoken == "0")
+                LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
+                mCache.erase(cur);
+			}
+            else
+            {
+                LLUUID id = exp[EXPERIENCE_ID].asUUID();
+                LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
+                if(private_key.notNull() || !exp.has("DoesNotExist"))
 				{
-					*max_age = 0;
-					return true;
+					fetch(id, true);
 				}
-				S32 val = atoi( subtoken.c_str() );
-				if (val > 0 && val < S32_MAX)
+				else
 				{
-					*max_age = val;
-					return true;
+                    LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
+					mCache.erase(cur);
 				}
-				return false;
 			}
 		}
-		return false;
 	}
-
-
-	void importFile(std::istream& istr)
+}
+	
+bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/)
+{
+	if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end()))
 	{
-		LLSD data;
-		S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
-		if(parse_count < 1) return;
-
-		LLSD experiences = data["experiences"];
-
-		LLUUID public_key;
-		LLSD::map_const_iterator it = experiences.beginMap();
-		for(; it != experiences.endMap() ; ++it)
-		{
-			public_key.set(it->first);
-			sCache[public_key]=it->second;
-		}
+		LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL;
 
-		LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL;
+        mRequestQueue.insert(key);
+		return true;
 	}
+	return false;
+}
 
-	void exportFile(std::ostream& ostr)
+void LLExperienceCache::insert(const LLSD& experience_data)
+{
+	if(experience_data.has(EXPERIENCE_ID))
 	{
-		LLSD experiences;
-
-		cache_t::const_iterator it =sCache.begin();
-		for( ; it != sCache.end() ; ++it)
-		{
-			if(!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() ||
-				it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID))
-				continue;
-
-			experiences[it->first.asString()] = it->second;
-		}
+        processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data);
+	}
+	else
+	{
+		LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
+	}
+}
 
-		LLSD data;
-		data["experiences"] = experiences;
+const LLSD& LLExperienceCache::get(const LLUUID& key)
+{
+	static const LLSD empty;
+	
+	if(key.isNull()) 
+		return empty;
+	cache_t::const_iterator it = mCache.find(key);
 
-		LLSDSerialize::toPrettyXML(data, ostr);
+	if (it != mCache.end())
+	{
+		return it->second;
 	}
+	fetch(key);
 
-	class LLExperienceResponder : public LLHTTPClient::Responder
-	{
-	public:
-		LLExperienceResponder(const ask_queue_t& keys)
-			:mKeys(keys)
-		{
+	return empty;
+}
 
-		}
+void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::ExperienceGetFn_t slot)
+{
+	if(key.isNull()) 
+		return;
 
-		/*virtual*/ void httpCompleted()
-		{
-			LLSD experiences = getContent()["experience_keys"];
-			LLSD::array_const_iterator it = experiences.beginArray();
-			for( /**/ ; it != experiences.endArray(); ++it)
-			{
-				const LLSD& row = *it;
-				LLUUID public_key = row[EXPERIENCE_ID].asUUID();
+	cache_t::const_iterator it = mCache.find(key);
+	if (it != mCache.end())
+	{
+		// ...name already exists in cache, fire callback now
+		callback_signal_t signal;
+		signal.connect(slot);
+			
+		signal(it->second);
+		return;
+	}
 
+	fetch(key);
 
-				LL_DEBUGS("ExperienceCache") << "Received result for " << public_key 
-					<< " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ;
+	signal_ptr signal = signal_ptr(new callback_signal_t());
+	
+	std::pair<signal_map_t::iterator, bool> result = mSignalMap.insert(signal_map_t::value_type(key, signal));
+	if (!result.second)
+		signal = (*result.first).second;
+	signal->connect(slot);
+}
 
-				processExperience(public_key, row);
-			}
+//=========================================================================
+void LLExperienceCache::fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Fetch Associated",
+        boost::bind(&LLExperienceCache::fetchAssociatedExperienceCoro, this, _1, objectId, itemId, fn));
+}
 
-			LLSD error_ids = getContent()["error_ids"];
-			LLSD::array_const_iterator errIt = error_ids.beginArray();
-			for( /**/ ; errIt != error_ids.endArray() ; ++errIt )
-			{
-				LLUUID id = errIt->asUUID();		
-				LLSD exp;
-				exp[EXPIRES]=DEFAULT_EXPIRATION;
-				exp[EXPERIENCE_ID] = id;
-				exp[PROPERTIES]=PROPERTY_INVALID;
-				exp[MISSING]=true;
-                exp[QUOTA] = DEFAULT_QUOTA;
-
-				processExperience(id, exp);
-				LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ;
-			}
+void LLExperienceCache::fetchAssociatedExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID objectId, LLUUID itemId, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+    std::string url = mCapability("GetMetadata");
+
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Metadata capability." << LL_ENDL;
+        return;
+    }
+
+    LLSD fields;
+    fields.append("experience");
+    LLSD data;
+    data["object-id"] = objectId;
+    data["item-id"] = itemId;
+    data["fields"] = fields;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, data);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if ((!status) || (!result.has("experience")))
+    {
+        LLSD failure;
+        if (!status)
+        {
+            failure["error"] = (LLSD::Integer)status.getType();
+            failure["message"] = status.getMessage();
+        }
+        else 
+        {
+            failure["error"] = -1;
+            failure["message"] = "no experience";
+        }
+        if (fn && !fn.empty())
+            fn(failure);
+        return;
+    }
+
+    LLUUID expId = result["experience"].asUUID();
+    get(expId, fn);
+}
 
-			LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL;
-		}
+//-------------------------------------------------------------------------
+void LLExperienceCache::findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Search Name",
+        boost::bind(&LLExperienceCache::findExperienceByNameCoro, this, _1, text, page, fn));
+}
 
-		/*virtual*/ void httpFailure()
-		{
- 			LL_WARNS("ExperienceCache") << "Request failed "<<getStatus()<<" "<<getReason()<< LL_ENDL;
- 			// We're going to construct a dummy record and cache it for a while,
- 			// either briefly for a 503 Service Unavailable, or longer for other
- 			// errors.
- 			F64 retry_timestamp = errorRetryTimestamp(getStatus());
- 
- 
- 			// Add dummy records for all agent IDs in this request
- 			ask_queue_t::const_iterator it = mKeys.begin();
- 			for ( ; it != mKeys.end(); ++it)
-			{
+void LLExperienceCache::findExperienceByNameCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string text, int page, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+    std::ostringstream url;
 
-				LLSD exp = get(it->first);
-                //leave the properties alone if we already have a cache entry for this xp
-                if(exp.isUndefined())
-                {
-                    exp[PROPERTIES]=PROPERTY_INVALID;
-                }
-				exp[EXPIRES]=retry_timestamp;
-				exp[EXPERIENCE_ID] = it->first;
-				exp["key_type"] = it->second;
-				exp["uuid"] = it->first;
-				exp["error"] = (LLSD::Integer)getStatus();
-                exp[QUOTA] = DEFAULT_QUOTA;
-
- 				LLExperienceCache::processExperience(it->first, exp);
- 			}
 
-		}
+    url << mCapability("FindExperienceByName")  << "?page=" << page << "&page_size=" << SEARCH_PAGE_SIZE << "&query=" << LLURI::escape(text);
 
-		// Return time to retry a request that generated an error, based on
-		// error type and headers.  Return value is seconds-since-epoch.
-		F64 errorRetryTimestamp(S32 status)
-		{
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url.str());
 
-			// Retry-After takes priority
-			LLSD retry_after = getResponseHeaders()["retry-after"];
-			if (retry_after.isDefined())
-			{
-				// We only support the delta-seconds type
-				S32 delta_seconds = retry_after.asInteger();
-				if (delta_seconds > 0)
-				{
-					// ...valid delta-seconds
-					return F64(delta_seconds);
-				}
-			}
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-			// If no Retry-After, look for Cache-Control max-age
-			F64 expires = 0.0;
-			if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires))
-			{
-				return expires;
-			}
+    if (!status)
+    {
+        fn(LLSD());
+        return;
+    }
 
-			// No information in header, make a guess
-			if (status == 503)
-			{
-				// ...service unavailable, retry soon
-				const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
-				return SERVICE_UNAVAILABLE_DELAY;
-			}
-			else if (status == 499)
-			{
-				// ...we were probably too busy, retry quickly
-				const F64 BUSY_DELAY = 10.0; // 10 seconds
-				return BUSY_DELAY;
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
 
-			}
-			else
-			{
-				// ...other unexpected error
-				const F64 DEFAULT_DELAY = 3600.0; // 1 hour
-				return DEFAULT_DELAY;
-			}
-		}
+    const LLSD& experiences = result["experience_keys"];
+    for (LLSD::array_const_iterator it = experiences.beginArray(); it != experiences.endArray(); ++it)
+    {
+        insert(*it);
+    }
 
-	private:
-		ask_queue_t mKeys;
-	};
+    fn(result);
+}
 
-	void requestExperiences() 
-	{
-		if(sAskQueue.empty() || sLookupURL.empty())
-			return;
+//-------------------------------------------------------------------------
+void LLExperienceCache::getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Group Experiences",
+        boost::bind(&LLExperienceCache::getGroupExperiencesCoro, this, _1, groupId, fn));
+}
 
-		F64 now = LLFrameTimer::getTotalSeconds();
+void LLExperienceCache::getGroupExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID groupId, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
 
-		const U32 EXP_URL_SEND_THRESHOLD = 3000;
-		const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH;
+    // search for experiences owned by the current group
+    std::string url = mCapability("GroupExperiences");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Group Experiences capability" << LL_ENDL;
+        return;
+    }
 
-		std::ostringstream ostr;
+    url += "?" + groupId.asString();
 
-		ask_queue_t keys;
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
 
-		ostr << sLookupURL << "?page_size=" << PAGE_SIZE;
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
+    if (!status)
+    {
+        fn(LLSD());
+        return;
+    }
 
-		int request_count = 0;
-		while(!sAskQueue.empty() && request_count < sMaximumLookups)
-		{
-			ask_queue_t::iterator it = sAskQueue.begin();
-			const LLUUID& key = it->first;
-			const std::string& key_type = it->second;
+    const LLSD& experienceIds = result["experience_ids"];
+    fn(experienceIds);
+}
 
-			ostr << '&' << key_type << '=' << key.asString() ;
-		
-			keys[key]=key_type;
-			request_count++;
+//-------------------------------------------------------------------------
+void LLExperienceCache::getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn)
+{
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Region Experiences",
+        boost::bind(&LLExperienceCache::regionExperiencesCoro, this, _1, regioncaps, false, LLSD(), fn));
+}
 
-			sPendingQueue[key] = now;
-			
-			if(ostr.tellp() > EXP_URL_SEND_THRESHOLD)
-			{
-				LL_DEBUGS("ExperienceCache") <<  "requestExperiences() query: " << ostr.str() << LL_ENDL;
-				LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys));
-				ostr.clear();
-				ostr.str(sLookupURL);
-				ostr << "?page_size=" << PAGE_SIZE;
-				keys.clear();
-			}
-			sAskQueue.erase(it);
-		}
+void LLExperienceCache::setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn)
+{
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Region Experiences",
+        boost::bind(&LLExperienceCache::regionExperiencesCoro, this, _1, regioncaps, true, experiences, fn));
+}
 
-		if(ostr.tellp() > sLookupURL.size())
-		{
-			LL_DEBUGS("ExperienceCache") <<  "requestExperiences() query 2: " << ostr.str() << LL_ENDL;
-			LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys));
-		}
-	}
+void LLExperienceCache::regionExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter,
+    CapabilityQuery_t regioncaps, bool update, LLSD experiences, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+    // search for experiences owned by the current group
+    std::string url = regioncaps("RegionExperiences");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
+        return;
+    }
+
+    LLSD result;
+    if (update)
+        result = httpAdapter->postAndSuspend(httpRequest, url, experiences);
+    else
+        result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+//      fn(LLSD());
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    fn(result);
 
-	bool isRequestPending(const LLUUID& public_key)
-	{
-		bool isPending = false;
-		const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+}
 
-		pending_queue_t::const_iterator it = sPendingQueue.find(public_key);
+//-------------------------------------------------------------------------
+void LLExperienceCache::getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
+    
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
+
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
 
-		if(it != sPendingQueue.end())
-		{
-			F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
-			isPending = (it->second > expire_time);
-		}
+void LLExperienceCache::setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    std::string url = mCapability("ExperiencePreferences");
+    if (url.empty())
+        return;
+    LLSD permData;
+    LLSD data;
+    permData["permission"] = permission;
+    data[experienceId.asString()] = permData;
+
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::putAndSuspend), _1, _2, _3, data, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
+
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
 
-		return isPending;
-	}
+void LLExperienceCache::forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
 
+    std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
 
-	void setLookupURL( const std::string& lookup_url )
-	{
-		sLookupURL = lookup_url;
-		if(!sLookupURL.empty())
-		{
-			sLookupURL += "id/";
-		}
-	}
 
-	bool hasLookupURL()
-	{
-		return !sLookupURL.empty();
-	}
+    permissionInvoker_fn invoker(boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, LLCore::HttpOptions::ptr_t(), LLCore::HttpHeaders::ptr_t()));
 
-	void idle()
-	{
 
-		const F32 SECS_BETWEEN_REQUESTS = 0.1f;
-		if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
-		{
-			return;
-		}
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "Preferences Set",
+        boost::bind(&LLExperienceCache::experiencePermissionCoro, this, _1, invoker, url, fn));
+}
 
-		// Must be large relative to above
-		const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
-		if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
-		{
-			eraseExpired();
-		}
+void LLExperienceCache::experiencePermissionCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, permissionInvoker_fn invokerfn, std::string url, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
 
+    // search for experiences owned by the current group
 
-		if(!sAskQueue.empty())
-		{
-			requestExperiences();
-		}
-	}
+    LLSD result = invokerfn(httpAdapter, httpRequest, url);
 
-	void erase( const LLUUID& key )
-	{
-		cache_t::iterator it = sCache.find(key);
-				
-		if(it != sCache.end())
-		{
-			sCache.erase(it);
-		}
-	}
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
 
-	void eraseExpired()
-	{
-		F64 now = LLFrameTimer::getTotalSeconds();
-		cache_t::iterator it = sCache.begin();
-		while (it != sCache.end())
-		{
-			cache_t::iterator cur = it;
-			LLSD& exp = cur->second;
-			++it;
+    if (status)
+    {
+        fn(result);
+    }
+}
 
-			if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
-			{
-                if(!exp.has(EXPERIENCE_ID))
-				{
-                    LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
-                    sCache.erase(cur);
-					}
-                else
-                {
-                    LLUUID id = exp[EXPERIENCE_ID].asUUID();
-                    LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
-                    if(private_key.notNull() || !exp.has("DoesNotExist"))
-					{
-						fetch(id, true);
-					}
-					else
-					{
-                        LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
-						sCache.erase(cur);
-					}
-				}
-			}
-		}
-	}
+//-------------------------------------------------------------------------
+void LLExperienceCache::getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "IsAdmin",
+        boost::bind(&LLExperienceCache::getExperienceAdminCoro, this, _1, experienceId, fn));
+}
 
-	
-	bool fetch( const LLUUID& key, bool refresh/* = true*/ ) 
-	{
-		if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end()))
-		{
-			LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ;
-			sAskQueue[key]=EXPERIENCE_ID;
+void LLExperienceCache::getExperienceAdminCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID experienceId, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
 
-			return true;
-		}
-		return false;
-	}
+    std::string url = mCapability("IsExperienceAdmin");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
+        return;
+    }
+    url += "?experience_id=" + experienceId.asString();
 
-	void insert(const LLSD& experience_data )
-	{
-		if(experience_data.has(EXPERIENCE_ID))
-		{
-            processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data);
-		}
-		else
-		{
-			LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
-		}
-	}
-	static LLSD empty;
-	const LLSD& get(const LLUUID& key)
-	{
-		if(key.isNull()) return empty;
-		cache_t::const_iterator it = sCache.find(key);
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+//     LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+//     LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-		if (it != sCache.end())
-		{
-			return it->second;
-		}
+    fn(result);
+}
 
-		fetch(key);
+//-------------------------------------------------------------------------
+void LLExperienceCache::updateExperience(LLSD updateData, ExperienceGetFn_t fn)
+{
+    if (mCapability.empty())
+    {
+        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL;
+        return;
+    }
+
+    LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "IsAdmin",
+        boost::bind(&LLExperienceCache::updateExperienceCoro, this, _1, updateData, fn));
+}
 
-		return empty;
-	}
-	void get( const LLUUID& key, callback_slot_t slot )
-	{
-		if(key.isNull()) return;
+void LLExperienceCache::updateExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLSD updateData, ExperienceGetFn_t fn)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
 
-		cache_t::const_iterator it = sCache.find(key);
-		if (it != sCache.end())
-		{
-			// ...name already exists in cache, fire callback now
-			callback_signal_t signal;
-			signal.connect(slot);
-			
-			signal(it->second);
-			return;
-		}
+    std::string url = mCapability("UpdateExperience");
+    if (url.empty())
+    {
+        LL_WARNS("ExperienceCache") << "No Region Experiences capability" << LL_ENDL;
+        return;
+    }
 
-		fetch(key);
+    updateData.erase(LLExperienceCache::QUOTA);
+    updateData.erase(LLExperienceCache::EXPIRES);
+    updateData.erase(LLExperienceCache::AGENT_ID);
 
-		// always store additional callback, even if request is pending
-		signal_map_t::iterator sig_it = sSignalMap.find(key);
-		if (sig_it == sSignalMap.end())
-		{
-			// ...new callback for this id
-			callback_signal_t* signal = new callback_signal_t();
-			signal->connect(slot);
-			sSignalMap[key] = signal;
-		}
-		else
-		{
-			// ...existing callback, bind additional slot
-			callback_signal_t* signal = sig_it->second;
-			signal->connect(slot);
-		}
-	}
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, updateData);
 
+    fn(result);
 }
 
-
-void LLExperienceCache::mapKeys( const LLSD& legacyKeys )
+//=========================================================================
+void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys)
 {
 	LLSD::array_const_iterator exp = legacyKeys.beginArray();
-	for(/**/ ; exp != legacyKeys.endArray() ; ++exp)
+	for (/**/; exp != legacyKeys.endArray(); ++exp)
 	{
-		if(exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY))
+        if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY))
 		{
-            privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()]=(*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
+            LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] = 
+                (*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID();
 		}
 	}
 }
 
-
-LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found)
+// Return time to retry a request that generated an error, based on
+// error type and headers.  Return value is seconds-since-epoch.
+F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers)
 {
-	if (private_key.isNull())
-		return LLUUID::null;
 
-    KeyMap::const_iterator it=privateToPublicKeyMap.find(private_key);
-    if(it == privateToPublicKeyMap.end())
+    // Retry-After takes priority
+    LLSD retry_after = headers["retry-after"];
+    if (retry_after.isDefined())
+    {
+        // We only support the delta-seconds type
+        S32 delta_seconds = retry_after.asInteger();
+        if (delta_seconds > 0)
+        {
+            // ...valid delta-seconds
+            return F64(delta_seconds);
+        }
+    }
+
+    // If no Retry-After, look for Cache-Control max-age
+    // Allow the header to override the default
+    LLSD cache_control_header = headers["cache-control"];
+    if (cache_control_header.isDefined())
+    {
+        S32 max_age = 0;
+        std::string cache_control = cache_control_header.asString();
+        if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age))
+        {
+            LL_WARNS("ExperienceCache")
+                << "got EXPIRES from headers, max_age " << max_age
+                << LL_ENDL;
+            return (F64)max_age;
+        }
+    }
+
+    // No information in header, make a guess
+    if (status == 503)
+    {
+        // ...service unavailable, retry soon
+        const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
+        return SERVICE_UNAVAILABLE_DELAY;
+    }
+    else if (status == 499)
+    {
+        // ...we were probably too busy, retry quickly
+        const F64 BUSY_DELAY = 10.0; // 10 seconds
+        return BUSY_DELAY;
+
+    }
+    else
+    {
+        // ...other unexpected error
+        const F64 DEFAULT_DELAY = 3600.0; // 1 hour
+        return DEFAULT_DELAY;
+    }
+}
+
+bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age)
+{
+	// Split the string on "," to get a list of directives
+	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+	tokenizer directives(cache_control, COMMA_SEPARATOR);
+	
+	tokenizer::iterator token_it = directives.begin();
+	for ( ; token_it != directives.end(); ++token_it)
 	{
-		if(null_if_not_found)
+		// Tokens may have leading or trailing whitespace
+		std::string token = *token_it;
+		LLStringUtil::trim(token);
+		
+		if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
 		{
-			return LLUUID::null;
+			// ...this token starts with max-age, so let's chop it up by "="
+			tokenizer subtokens(token, EQUALS_SEPARATOR);
+			tokenizer::iterator subtoken_it = subtokens.begin();
+			
+			// Must have a token
+			if (subtoken_it == subtokens.end()) return false;
+			std::string subtoken = *subtoken_it;
+			
+			// Must exactly equal "max-age"
+			LLStringUtil::trim(subtoken);
+			if (subtoken != MAX_AGE) return false;
+			
+			// Must have another token
+			++subtoken_it;
+			if (subtoken_it == subtokens.end()) return false;
+			subtoken = *subtoken_it;
+			
+			// Must be a valid integer
+			// *NOTE: atoi() returns 0 for invalid values, so we have to
+			// check the string first.
+			// *TODO: Do servers ever send "0000" for zero?  We don't handle it
+			LLStringUtil::trim(subtoken);
+			if (subtoken == "0")
+			{
+				*max_age = 0;
+				return true;
+			}
+			S32 val = atoi( subtoken.c_str() );
+			if (val > 0 && val < S32_MAX)
+			{
+				*max_age = val;
+				return true;
+			}
+			return false;
 		}
-		return private_key;
 	}
-	LL_WARNS("LLExperience") << "converted private key " << private_key << " to experience_id " << it->second << LL_ENDL;
-	return it->second;
+	return false;
 }
+
+
+
+
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index e669ee888efba679f281197adfa7f36b8979ee13..1002b33f801865acf6c7665cc65da017ecee7f78 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -30,75 +30,155 @@
 #define LL_LLEXPERIENCECACHE_H
 
 #include "linden_common.h"
+#include "llsingleton.h"
+#include "llframetimer.h"
+#include "llsd.h"
+#include "llcorehttputil.h"
 #include <boost/signals2.hpp>
+#include <boost/function.hpp>
 
 class LLSD;
 class LLUUID;
 
 
-
-namespace LLExperienceCache
+class LLExperienceCache: public LLSingleton < LLExperienceCache >
 {
-	const std::string PRIVATE_KEY	= "private_id";
-    const std::string MISSING       = "DoesNotExist";
-
-    const std::string AGENT_ID      = "agent_id";
-    const std::string GROUP_ID      = "group_id";
-	const std::string EXPERIENCE_ID	= "public_id";
-	const std::string NAME			= "name";
-	const std::string PROPERTIES	= "properties";
-	const std::string EXPIRES		= "expiration";  
-    const std::string DESCRIPTION	= "description";
-    const std::string QUOTA         = "quota";
-    const std::string MATURITY      = "maturity";
-    const std::string METADATA      = "extended_metadata";
-    const std::string SLURL         = "slurl";
-
-
-	// should be in sync with experience-api/experiences/models.py
-	const int PROPERTY_INVALID		= 1 << 0;
-	const int PROPERTY_PRIVILEGED	= 1 << 3;
-	const int PROPERTY_GRID			= 1 << 4;
-	const int PROPERTY_PRIVATE		= 1 << 5;
-	const int PROPERTY_DISABLED		= 1 << 6;  
-	const int PROPERTY_SUSPENDED	    = 1 << 7;
-
-
-	// default values
-	const static F64 DEFAULT_EXPIRATION = 600.0;
-	const static S32 DEFAULT_QUOTA = 128; // this is megabytes
-
-	// Callback types for get() below
-	typedef boost::signals2::signal<void (const LLSD& experience)>
-		callback_signal_t;
-	typedef callback_signal_t::slot_type callback_slot_t;
+    friend class LLSingleton < LLExperienceCache > ;
+
+public:
+    typedef boost::function<std::string(const std::string &)> CapabilityQuery_t;
+    typedef boost::function<void(const LLSD &)> ExperienceGetFn_t;
+
+    void setCapabilityQuery(CapabilityQuery_t queryfn);
+    void cleanup();
+
+    //-------------------------------------------
+    // Cache methods 
+    void erase(const LLUUID& key);
+    bool fetch(const LLUUID& key, bool refresh = false);
+    void insert(const LLSD& experience_data);
+    const LLSD& get(const LLUUID& key);
+    void get(const LLUUID& key, ExperienceGetFn_t slot); // If name information is in cache, callback will be called immediately.
+
+    bool isRequestPending(const LLUUID& public_key);
+
+    //-------------------------------------------
+    void fetchAssociatedExperience(const LLUUID& objectId, const LLUUID& itemId, ExperienceGetFn_t fn);
+    void findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn);
+    void getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn);
+
+    // the Get/Set Region Experiences take a CapabilityQuery to get the capability since 
+    // the region being queried may not be the region that the agent is standing on.
+    void getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn);
+    void setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn);
+
+    void getExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
+    void setExperiencePermission(const LLUUID &experienceId, const std::string &permission, ExperienceGetFn_t fn);
+    void forgetExperiencePermission(const LLUUID &experienceId, ExperienceGetFn_t fn);
+
+    void getExperienceAdmin(const LLUUID &experienceId, ExperienceGetFn_t fn);
+
+    void updateExperience(LLSD updateData, ExperienceGetFn_t fn);
+        //-------------------------------------------
+    static const std::string NAME;			// "name"
+    static const std::string EXPERIENCE_ID;	// "public_id"
+    static const std::string AGENT_ID;      // "agent_id"
+    static const std::string GROUP_ID;      // "group_id"
+    static const std::string PROPERTIES;	// "properties"
+    static const std::string EXPIRES;		// "expiration"  
+    static const std::string DESCRIPTION;	// "description"
+    static const std::string QUOTA;         // "quota"
+    static const std::string MATURITY;      // "maturity"
+    static const std::string METADATA;      // "extended_metadata"
+    static const std::string SLURL;         // "slurl"
+
+    static const std::string MISSING;       // "DoesNotExist"
+
+    // should be in sync with experience-api/experiences/models.py
+    static const int PROPERTY_INVALID;		// 1 << 0
+    static const int PROPERTY_PRIVILEGED;	// 1 << 3
+    static const int PROPERTY_GRID;			// 1 << 4
+    static const int PROPERTY_PRIVATE;		// 1 << 5
+    static const int PROPERTY_DISABLED;		// 1 << 6  
+    static const int PROPERTY_SUSPENDED;	// 1 << 7
+
+private:
+    LLExperienceCache();
+    virtual ~LLExperienceCache();
+
+    virtual void initSingleton();
+
+    typedef boost::function<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLCore::HttpRequest::ptr_t, std::string)> permissionInvoker_fn;
+
+    // Callback types for get() 
+    typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
+	typedef boost::shared_ptr<callback_signal_t> signal_ptr;
+	// May have multiple callbacks for a single ID, which are
+	// represented as multiple slots bound to the signal.
+	// Avoid copying signals via pointers.
+	typedef std::map<LLUUID, signal_ptr> signal_map_t;
 	typedef std::map<LLUUID, LLSD> cache_t;
-
-
-	void setLookupURL(const std::string& lookup_url);
-	bool hasLookupURL();
-
-	void setMaximumLookups(int maximumLookups);
-
-	void idle();
-	void exportFile(std::ostream& ostr);
-	void importFile(std::istream& istr);
-	void initClass();
-	void bootstrap(const LLSD& legacyKeys, int initialExpiration);
 	
-	void erase(const LLUUID& key);
-	bool fetch(const LLUUID& key, bool refresh=false);
-	void insert(const LLSD& experience_data);
-	const LLSD& get(const LLUUID& key);
-
-	// If name information is in cache, callback will be called immediately.
-	void get(const LLUUID& key, callback_slot_t slot);
+	typedef std::set<LLUUID> RequestQueue_t;
+    typedef std::map<LLUUID, F64> PendingQueue_t;
 
+	//--------------------------------------------
+	static const std::string PRIVATE_KEY;	// "private_id"
+	
+	// default values
+	static const F64 DEFAULT_EXPIRATION; 	// 600.0
+	static const S32 DEFAULT_QUOTA; 		// 128 this is megabytes
+    static const int SEARCH_PAGE_SIZE;
+	
+//--------------------------------------------
+    void processExperience(const LLUUID& public_key, const LLSD& experience);
+
+//--------------------------------------------
+	cache_t			mCache;
+	signal_map_t	mSignalMap;	
+	RequestQueue_t	mRequestQueue;
+    PendingQueue_t  mPendingQueue;
+
+    LLFrameTimer    mEraseExpiredTimer;    // Periodically clean out expired entries from the cache
+    CapabilityQuery_t mCapability;
+    std::string     mCacheFileName;
+    bool            mShutdown;
+
+    void idleCoro();
+	void eraseExpired();
+    void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t);
+    void requestExperiences();
+
+    void fetchAssociatedExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLUUID, LLUUID, ExperienceGetFn_t);
+    void findExperienceByNameCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, int, ExperienceGetFn_t);
+    void getGroupExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLUUID , ExperienceGetFn_t);
+    void regionExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, CapabilityQuery_t regioncaps, bool update, LLSD experiences, ExperienceGetFn_t fn);
+    void experiencePermissionCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, permissionInvoker_fn invokerfn, std::string url, ExperienceGetFn_t fn);
+    void getExperienceAdminCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLUUID experienceId, ExperienceGetFn_t fn);
+    void updateExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, LLSD updateData, ExperienceGetFn_t fn);
+
+    void bootstrap(const LLSD& legacyKeys, int initialExpiration);
+    void exportFile(std::ostream& ostr) const;
+    void importFile(std::istream& istr);
+
+    // 
 	const cache_t& getCached();
 
 	// maps an experience private key to the experience id
 	LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
 
+    //=====================================================================
+    inline friend std::ostream &operator << (std::ostream &os, const LLExperienceCache &cache)
+    {
+        cache.exportFile(os);
+        return os;
+    }
+
+    inline friend std::istream &operator >> (std::istream &is, LLExperienceCache &cache)
+    {
+        cache.importFile(is);
+        return is;
+    }
 };
 
 #endif // LL_LLEXPERIENCECACHE_H
diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp
index 63c15f0d5ee7bb911e5008ef705cd62b7cc0f8bd..ae5c2ecf698a33c421713d2c2ba0fd4bdd108d49 100755
--- a/indra/llmessage/llhost.cpp
+++ b/indra/llmessage/llhost.cpp
@@ -41,8 +41,6 @@
 	#include <arpa/inet.h>
 #endif
 
-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(":");
diff --git a/indra/llmessage/llhost.h b/indra/llmessage/llhost.h
index 0cf52a4151c7af4f517cf63161d95180e0da7aba..79cad4b123df2d4ec2caa31af207332cfc670fb3 100755
--- a/indra/llmessage/llhost.h
+++ b/indra/llmessage/llhost.h
@@ -40,9 +40,8 @@ class LLHost {
 protected:
 	U32			mPort;
 	U32         mIP;
+    std::string mUntrustedSimCap;
 public:
-	
-	static LLHost invalid;
 
 	// CREATORS
 	LLHost()
@@ -89,13 +88,17 @@ class LLHost {
 	// READERS
 	U32		getAddress() const							{ return mIP; }
 	U32		getPort() const								{ return mPort; }
-	BOOL	isOk() const								{ return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
+	bool	isOk() const								{ return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
+    bool    isInvalid()                                 { return (mIP == INVALID_HOST_IP_ADDRESS) || (mPort == INVALID_PORT); }
 	size_t	hash() const								{ return (mIP << 16) | (mPort & 0xffff); }
 	std::string getString() const;
 	std::string getIPString() const;
 	std::string getHostName() const;
 	std::string getIPandPort() const;
 
+    std::string getUntrustedSimulatorCap() const        { return mUntrustedSimCap; }
+    void setUntrustedSimulatorCap(const std::string &capurl) { mUntrustedSimCap = capurl; }
+
 	friend std::ostream& operator<< (std::ostream& os, const LLHost &hh);
 
 	// This operator is not well defined. does it expect a
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
deleted file mode 100755
index e20215444505f772e3c08b7dfa5cbfb18e514ddd..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ /dev/null
@@ -1,1454 +0,0 @@
-/** 
- * @file llhttpassetstorage.cpp
- * @brief Subclass capable of loading asset data to/from an external
- * source. Currently, a web server accessed via curl
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llhttpassetstorage.h"
-
-#include <sys/stat.h>
-
-#include "indra_constants.h"
-#include "message.h"
-#include "llproxy.h"
-#include "llvfile.h"
-#include "llvfs.h"
-#include "llxfer.h"
-
-#ifdef LL_USESYSTEMLIBS
-# include <zlib.h>
-#else
-# include "zlib/zlib.h"
-#endif
-
-const	char* const	LOCAL_ASSET_URL_FORMAT		= "http://%s:12041/asset";
-
-const U32 MAX_RUNNING_REQUESTS = 1;
-
-// Try for 30 minutes for now.
-const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f;
-
-const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096;
-
-/////////////////////////////////////////////////////////////////////////////////
-// LLTempAssetData
-// An asset not stored on central asset store, but on a simulator node somewhere.
-/////////////////////////////////////////////////////////////////////////////////
-struct LLTempAssetData
-{
-	LLUUID	mAssetID;
-	LLUUID	mAgentID;
-	std::string	mHostName;
-};
-
-/////////////////////////////////////////////////////////////////////////////////
-// LLHTTPAssetRequest
-/////////////////////////////////////////////////////////////////////////////////
-
-class LLHTTPAssetRequest : public LLAssetRequest
-{
-public:
-	LLHTTPAssetRequest(LLHTTPAssetStorage *asp, const LLUUID &uuid, 
-					   LLAssetType::EType type, LLAssetStorage::ERequestType rt,
-					   const std::string& url, CURLM *curl_multi);
-	virtual ~LLHTTPAssetRequest();
-	
-	void setupCurlHandle();
-	void cleanupCurlHandle();
-
-	void   	prepareCompressedUpload();
-	void	finishCompressedUpload();
-	size_t	readCompressedData(void* data, size_t size);
-
-	static size_t curlCompressedUploadCallback(
-					void *data, size_t size, size_t nmemb, void *user_data);
-
-	virtual LLSD getTerseDetails() const;
-	virtual LLSD getFullDetails() const;
-
-public:
-	LLHTTPAssetStorage *mAssetStoragep;
-
-	CURL  *mCurlHandle;
-	CURLM *mCurlMultiHandle;
-	std::string mURLBuffer;
-	struct curl_slist *mHTTPHeaders;
-	LLVFile *mVFile;
-	LLUUID  mTmpUUID;
-	LLAssetStorage::ERequestType mRequestType;
-
-	bool		mZInitialized;
-	z_stream	mZStream;
-	char*		mZInputBuffer;
-	bool		mZInputExhausted;
-
-	FILE *mFP;
-};
-
-
-LLHTTPAssetRequest::LLHTTPAssetRequest(LLHTTPAssetStorage *asp, 
-						const LLUUID &uuid, 
-						LLAssetType::EType type, 
-						LLAssetStorage::ERequestType rt,
-						const std::string& url, 
-						CURLM *curl_multi)
-	: LLAssetRequest(uuid, type),
-	  mZInitialized(false)
-{
-	memset(&mZStream, 0, sizeof(mZStream)); // we'll initialize this later, but for now zero the whole C-style struct to avoid debug/coverity noise
-	mAssetStoragep = asp;
-	mCurlHandle = NULL;
-	mCurlMultiHandle = curl_multi;
-	mVFile = NULL;
-	mRequestType = rt;
-	mHTTPHeaders = NULL;
-	mFP = NULL;
-	mZInputBuffer = NULL;
-	mZInputExhausted = false;
-	
-	mURLBuffer = url;
-}
-
-LLHTTPAssetRequest::~LLHTTPAssetRequest()
-{
-	// Cleanup/cancel the request
-	if (mCurlHandle)
-	{
-		curl_multi_remove_handle(mCurlMultiHandle, mCurlHandle);
-		cleanupCurlHandle();
-	}
-	if (mHTTPHeaders)
-	{
-		curl_slist_free_all(mHTTPHeaders);
-	}
-	delete   mVFile;
-	finishCompressedUpload();
-}
-
-// virtual
-LLSD LLHTTPAssetRequest::getTerseDetails() const
-{
-	LLSD sd = LLAssetRequest::getTerseDetails();
-
-	sd["url"] = mURLBuffer;
-
-	return sd;
-}
-
-// virtual
-LLSD LLHTTPAssetRequest::getFullDetails() const
-{
-	LLSD sd = LLAssetRequest::getFullDetails();
-
-	if (mCurlHandle)
-	{
-		long curl_response = -1;
-		long curl_connect = -1;
-		double curl_total_time = -1.0f;
-		double curl_size_upload = -1.0f;
-		double curl_size_download = -1.0f;
-		double curl_content_length_upload = -1.0f;
-		double curl_content_length_download = -1.0f;
-		long curl_request_size = -1;
-		const char* curl_content_type = NULL;
-
-		curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CODE, &curl_response);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CONNECTCODE, &curl_connect);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &curl_total_time);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_UPLOAD,  &curl_size_upload);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &curl_size_download);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_UPLOAD,   &curl_content_length_upload);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curl_content_length_download);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_REQUEST_SIZE, &curl_request_size);
-		curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_TYPE, &curl_content_type);
-
-		sd["curl_response_code"] = (int) curl_response;
-		sd["curl_http_connect_code"] = (int) curl_connect;
-		sd["curl_total_time"] = curl_total_time;
-		sd["curl_size_upload"]   = curl_size_upload;
-		sd["curl_size_download"] = curl_size_download;
-		sd["curl_content_length_upload"]   =  curl_content_length_upload;
-		sd["curl_content_length_download"] =  curl_content_length_download;
-		sd["curl_request_size"] = (int) curl_request_size;
-		if (curl_content_type)
-		{
-			sd["curl_content_type"] = curl_content_type;
-		}
-		else
-		{
-			sd["curl_content_type"] = "";
-		}
-	}
-
-	sd["temp_id"] = mTmpUUID;
-	sd["request_type"] = LLAssetStorage::getRequestName(mRequestType);
-	sd["z_initialized"] = mZInitialized;
-	sd["z_input_exhausted"] = mZInputExhausted;
-
-	S32 file_size = -1;
-	if (mFP)
-	{
-		struct stat file_stat;
-		int file_desc = fileno(mFP);
-		if ( fstat(file_desc, &file_stat) == 0)
-		{
-			file_size = file_stat.st_size;
-		}
-	}
-	sd["file_size"] = file_size;
-
-	return sd;
-}
-
-
-void LLHTTPAssetRequest::setupCurlHandle()
-{
-	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC
-	mCurlHandle = LLCurl::newEasyHandle();
-	llassert_always(mCurlHandle != NULL) ;
-
-	// Apply proxy settings if configured to do so
-	LLProxy::getInstance()->applyProxySettings(mCurlHandle);
-
-	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
-	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
-	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str());
-	curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
-	if (LLAssetStorage::RT_DOWNLOAD == mRequestType)
-	{
-		curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
-		// only do this on downloads, as uploads 
-		// to some apache configs (like our test grids)
-		// mistakenly claim the response is gzip'd if the resource
-		// name ends in .gz, even though in a PUT, the response is
-		// just plain HTML saying "created"
-	}
-	/* Remove the Pragma: no-cache header that libcurl inserts by default;
-	   we want the cached version, if possible. */
-	if (mZInitialized)
-	{
-		curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, "");
-			// disable use of proxy, which can't handle chunked transfers
-	}
-	mHTTPHeaders = curl_slist_append(mHTTPHeaders, "Pragma:");
-
-	// bug in curl causes DNS to be cached for too long a time, 0 sets it to never cache DNS results internally (to curl)
-	curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
-	
-	// resist the temptation to explicitly add the Transfer-Encoding: chunked
-	// header here - invokes a libCURL bug
-	curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mHTTPHeaders);
-	if (mAssetStoragep)
-	{
-		// Set the appropriate pending upload or download flag
-		mAssetStoragep->addRunningRequest(mRequestType, this);
-	}
-	else
-	{
-		LL_ERRS() << "LLHTTPAssetRequest::setupCurlHandle - No asset storage associated with this request!" << LL_ENDL;
-	}
-}
-
-void LLHTTPAssetRequest::cleanupCurlHandle()
-{
-	LLCurl::deleteEasyHandle(mCurlHandle);
-	if (mAssetStoragep)
-	{
-		// Terminating a request.  Thus upload or download is no longer pending.
-		mAssetStoragep->removeRunningRequest(mRequestType, this);
-	}
-	else
-	{
-		LL_ERRS() << "LLHTTPAssetRequest::~LLHTTPAssetRequest - No asset storage associated with this request!" << LL_ENDL;
-	}
-	mCurlHandle = NULL;
-}
-
-void LLHTTPAssetRequest::prepareCompressedUpload()
-{
-	mZStream.next_in = Z_NULL;
-	mZStream.avail_in = 0;
-	mZStream.zalloc = Z_NULL;
-	mZStream.zfree = Z_NULL;
-	mZStream.opaque = Z_NULL;
-
-	int r = deflateInit2(&mZStream,
-			1,			// compression level
-			Z_DEFLATED,	// the only method defined
-			15 + 16,	// the default windowBits + gzip header flag
-			8,			// the default memLevel
-			Z_DEFAULT_STRATEGY);
-
-	if (r != Z_OK)
-	{
-		LL_ERRS() << "LLHTTPAssetRequest::prepareCompressedUpload defalateInit2() failed" << LL_ENDL;
-	}
-
-	mZInitialized = true;
-	mZInputBuffer = new char[COMPRESSED_INPUT_BUFFER_SIZE];
-	mZInputExhausted = false;
-
-	mVFile = new LLVFile(gAssetStorage->mVFS,
-					getUUID(), getType(), LLVFile::READ);
-}
-
-void LLHTTPAssetRequest::finishCompressedUpload()
-{
-	if (mZInitialized)
-	{
-		LL_INFOS() << "LLHTTPAssetRequest::finishCompressedUpload: "
-			<< "read " << mZStream.total_in << " byte asset file, "
-			<< "uploaded " << mZStream.total_out << " byte compressed asset"
-			<< LL_ENDL;
-
-		deflateEnd(&mZStream);
-		delete[] mZInputBuffer;
-	}
-}
-
-size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size)
-{
-	llassert(mZInitialized);
-
-	mZStream.next_out = (Bytef*)data;
-	mZStream.avail_out = size;
-
-	while (mZStream.avail_out > 0)
-	{
-		if (mZStream.avail_in == 0 && !mZInputExhausted)
-		{
-			S32 to_read = llmin(COMPRESSED_INPUT_BUFFER_SIZE,
-							(S32)(mVFile->getSize() - mVFile->tell()));
-			
-			if ( to_read > 0 )
-			{
-				mVFile->read((U8*)mZInputBuffer, to_read); /*Flawfinder: ignore*/
-				mZStream.next_in = (Bytef*)mZInputBuffer;
-				mZStream.avail_in = mVFile->getLastBytesRead();
-			}
-
-			mZInputExhausted = mZStream.avail_in == 0;
-		}
-
-		int r = deflate(&mZStream,
-					mZInputExhausted ? Z_FINISH : Z_NO_FLUSH);
-
-		if (r == Z_STREAM_END || r < 0 || mZInputExhausted)
-		{
-			if (r < 0)
-			{
-				LL_WARNS() << "LLHTTPAssetRequest::readCompressedData: deflate returned error code " 
-						<< (S32) r << LL_ENDL;
-			}
-			break;
-		}
-	}
-
-	return size - mZStream.avail_out;
-}
-
-//static
-size_t LLHTTPAssetRequest::curlCompressedUploadCallback(
-		void *data, size_t size, size_t nmemb, void *user_data)
-{
-	size_t num_read = 0;
-
-	if (gAssetStorage)
-	{
-		CURL *curl_handle = (CURL *)user_data;
-		LLHTTPAssetRequest *req = NULL;
-		curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req);
-		if (req)
-		{
-			num_read = req->readCompressedData(data, size * nmemb);
-		}
-	}
-
-	return num_read;
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-// LLHTTPAssetStorage
-/////////////////////////////////////////////////////////////////////////////////
-
-
-LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
-									 LLVFS *vfs, LLVFS *static_vfs, 
-									 const LLHost &upstream_host,
-									 const std::string& web_host,
-									 const std::string& local_web_host,
-									 const std::string& host_name)
-	: LLAssetStorage(msg, xfer, vfs, static_vfs, upstream_host)
-{
-	_init(web_host, local_web_host, host_name);
-}
-
-LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
-									   LLVFS *vfs,
-									   LLVFS *static_vfs,
-									   const std::string& web_host,
-									   const std::string& local_web_host,
-									   const std::string& host_name)
-	: LLAssetStorage(msg, xfer, vfs, static_vfs)
-{
-	_init(web_host, local_web_host, host_name);
-}
-
-void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name)
-{
-	mBaseURL = web_host;
-	mLocalBaseURL = local_web_host;
-	mHostName = host_name;
-
-	// curl_global_init moved to LLCurl::initClass()
-	
-	mCurlMultiHandle = LLCurl::newMultiHandle() ;
-	llassert_always(mCurlMultiHandle != NULL) ;
-}
-
-LLHTTPAssetStorage::~LLHTTPAssetStorage()
-{
-	LLCurl::deleteMultiHandle(mCurlMultiHandle);
-	mCurlMultiHandle = NULL;
-	
-	// curl_global_cleanup moved to LLCurl::initClass()
-}
-
-// storing data is simpler than getting it, so we just overload the whole method
-void LLHTTPAssetStorage::storeAssetData(
-	const LLUUID& uuid,
-	LLAssetType::EType type,
-	LLAssetStorage::LLStoreAssetCallback callback,
-	void* user_data,
-	bool temp_file,
-	bool is_priority,
-	bool store_local,
-	const LLUUID& requesting_agent_id,
-	bool user_waiting,
-	F64Seconds timeout)
-{
-	if (mVFS->getExists(uuid, type)) // VFS treats nonexistant and zero-length identically
-	{
-		LLAssetRequest *req = new LLAssetRequest(uuid, type);
-		req->mUpCallback    = callback;
-		req->mUserData      = user_data;
-		req->mRequestingAgentID = requesting_agent_id;
-		req->mIsUserWaiting = user_waiting;
-		req->mTimeout       = timeout;
-
-		// LLAssetStorage metric: Successful Request
-		S32 size = mVFS->getSize(uuid, type);
-		const char *message;
-		if( store_local )
-		{
-			message = "Added to local upload queue";
-		}
-		else
-		{
-			message = "Added to upload queue";
-		}
-		reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, size, MR_OKAY, __FILE__, __LINE__, message );
-
-		// this will get picked up and transmitted in checkForTimeouts
-		if(store_local)
-		{
-			mPendingLocalUploads.push_back(req);
-		}
-		else if(is_priority)
-		{
-			mPendingUploads.push_front(req);
-		}
-		else
-		{
-			mPendingUploads.push_back(req);
-		}
-	}
-	else
-	{
-		LL_WARNS() << "AssetStorage: attempt to upload non-existent vfile " << uuid << ":" << LLAssetType::lookup(type) << LL_ENDL;
-		if (callback)
-		{
-			// LLAssetStorage metric: Zero size VFS
-			reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
-			callback(uuid, user_data,  LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
-		}
-	}
-}
-
-// virtual
-void LLHTTPAssetStorage::storeAssetData(
-	const std::string& filename,
-	const LLUUID& asset_id,
-	LLAssetType::EType asset_type,
-	LLStoreAssetCallback callback,
-	void* user_data,
-	bool temp_file,
-	bool is_priority,
-	bool user_waiting,
-	F64Seconds timeout)
-{
-	LL_INFOS() << "LLAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
-
-	LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
-
-	legacy->mUpCallback = callback;
-	legacy->mUserData = user_data;
-
-	FILE *fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
-	S32 size = 0;
-	if (fp)
-	{
-		fseek(fp, 0, SEEK_END);
-		size = ftell(fp);
-		fseek(fp, 0, SEEK_SET);
-	}
-
-	if( size )
-	{
-		LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
-
-		file.setMaxSize(size);
-
-		const S32 buf_size = 65536;
-		U8 copy_buf[buf_size];
-		while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
-		{
-			file.write(copy_buf, size);
-		}
-		fclose(fp);
-
-		// if this upload fails, the caller needs to setup a new tempfile for us
-		if (temp_file)
-		{
-			LLFile::remove(filename);
-		}
-		
-		// LLAssetStorage metric: Success not needed; handled in the overloaded method here:
-		storeAssetData(
-			asset_id,
-			asset_type,
-			legacyStoreDataCallback,
-			(void**)legacy,
-			temp_file,
-			is_priority,
-			false,
-			LLUUID::null,
-			user_waiting,
-			timeout);
-	}
-	else // !size
-	{
-		if( fp )
-		{
-			// LLAssetStorage metric: Zero size
-			reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
-			fclose( fp );
-		}
-		else
-		{
-			// LLAssetStorage metric: Missing File
-			reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
-		}
-		if (callback)
-		{
-			callback(LLUUID::null, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
-		}
-		delete legacy;
-	}
-}
-
-// virtual
-LLSD LLHTTPAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt,
-										LLAssetType::EType asset_type,
-										const std::string& detail_prefix) const
-{
-	LLSD sd = LLAssetStorage::getPendingDetails(rt, asset_type, detail_prefix);
-	const request_list_t* running = getRunningList(rt);
-	if (running)
-	{
-		// Loop through the pending requests sd, and add extra info about its running status.
-		S32 num_pending = sd["requests"].size();
-		S32 i;
-		for (i = 0; i < num_pending; ++i)
-		{
-			LLSD& pending = sd["requests"][i];
-			// See if this pending request is running.
-			const LLAssetRequest* req = findRequest(running, 
-									LLAssetType::lookup(pending["type"].asString()),
-									pending["asset_id"]);
-			if (req)
-			{
-				// Keep the detail_url so we don't have to rebuild it.
-				LLURI detail_url = pending["detail"];
-				pending = req->getTerseDetails();
-				pending["detail"] = detail_url;
-				pending["is_running"] = true;
-			}
-			else
-			{
-				pending["is_running"] = false;
-			}
-		}
-	}
-	return sd;
-}
-
-// virtual
-LLSD LLHTTPAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
-										LLAssetType::EType asset_type,
-										const LLUUID& asset_id) const
-{
-	// Look for this asset in the running list first.
-	const request_list_t* running = getRunningList(rt);
-	if (running)
-	{
-		LLSD sd = LLAssetStorage::getPendingRequestImpl(running, asset_type, asset_id);
-		if (sd)
-		{
-			sd["is_running"] = true;
-			return sd;
-		}
-	}
-	LLSD sd = LLAssetStorage::getPendingRequest(rt, asset_type, asset_id);
-	if (sd)
-	{
-		sd["is_running"] = false;
-	}
-	return sd;
-}
-
-// virtual
-bool LLHTTPAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
-											LLAssetType::EType asset_type,
-											const LLUUID& asset_id)
-{
-	// Try removing this from the running list first.
-	request_list_t* running = getRunningList(rt);
-	if (running)
-	{
-		LLAssetRequest* req = findRequest(running, asset_type, asset_id);
-		if (req)
-		{
-			// Remove this request from the running list to get it out of curl.
-			running->remove(req);
-			
-			// Find this request in the pending list, so we can move it to the end of the line.
-			request_list_t* pending = getRequestList(rt);
-			if (pending)
-			{
-				request_list_t::iterator result = std::find_if(pending->begin(), pending->end(),
-										std::bind2nd(ll_asset_request_equal<LLAssetRequest*>(), req));
-				if (pending->end() != result)
-				{
-					// This request was found in the pending list.  Move it to the end!
-					LLAssetRequest* pending_req = *result;
-					pending->remove(pending_req);
-
-					if (!pending_req->mIsUserWaiting)				//A user is waiting on this request.  Toss it.
-					{
-						pending->push_back(pending_req);
-					}
-					else
-					{
-						if (pending_req->mUpCallback)	//Clean up here rather than _callUploadCallbacks because this request is already cleared the req.
-						{
-							pending_req->mUpCallback(pending_req->getUUID(), pending_req->mUserData, -1, LL_EXSTAT_REQUEST_DROPPED);
-						}
-
-					}
-
-					LL_INFOS() << "Asset " << getRequestName(rt) << " request for "
-							<< asset_id << "." << LLAssetType::lookup(asset_type)
-							<< " removed from curl and placed at the end of the pending queue."
-							<< LL_ENDL;
-				}
-				else
-				{
-					LL_WARNS() << "Unable to find pending " << getRequestName(rt) << " request for "
-							<< asset_id << "." << LLAssetType::lookup(asset_type) << LL_ENDL;
-				}
-			}
-			delete req;
-
-			return true;
-		}
-	}
-	return LLAssetStorage::deletePendingRequest(rt, asset_type, asset_id);
-}
-
-// internal requester, used by getAssetData in superclass
-void LLHTTPAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
-										  void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
-										  void *user_data, BOOL duplicate,
-										   BOOL is_priority)
-{
-	// stash the callback info so we can find it after we get the response message
-	LLAssetRequest *req = new LLAssetRequest(uuid, type);
-	req->mDownCallback = callback;
-	req->mUserData = user_data;
-	req->mIsPriority = is_priority;
-
-	// this will get picked up and downloaded in checkForTimeouts
-
-	//
-	// HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK!  Asset requests were taking too long and timing out.
-	// Since texture requests are the LEAST sensitive (on the simulator) to being delayed, add
-	// non-texture requests to the front, and add texture requests to the back.  The theory is
-	// that we always want them first, even if they're out of order.
-	//
-	
-	if (req->getType() == LLAssetType::AT_TEXTURE)
-	{
-		mPendingDownloads.push_back(req);
-	}
-	else
-	{
-		mPendingDownloads.push_front(req);
-	}
-}
-
-LLAssetRequest* LLHTTPAssetStorage::findNextRequest(LLAssetStorage::request_list_t& pending, 
-													LLAssetStorage::request_list_t& running)
-{
-	// Early exit if the running list is full, or we don't have more pending than running.
-	if (running.size() >= MAX_RUNNING_REQUESTS
-		|| pending.size() <= running.size()) return NULL;
-
-	// Look for the first pending request that is not already running.
-	request_list_t::iterator running_begin = running.begin();
-	request_list_t::iterator running_end   = running.end();
-
-	request_list_t::iterator pending_iter = pending.begin();
-
-	// Loop over all pending requests until we miss finding it in the running list.
-	for (; pending_iter != pending.end(); ++pending_iter)
-	{
-		LLAssetRequest* req = *pending_iter;
-		// Look for this pending request in the running list.
-		if (running_end == std::find_if(running_begin, running_end, 
-						std::bind2nd(ll_asset_request_equal<LLAssetRequest*>(), req)))
-		{
-			// It isn't running!  Return it.
-			return req;
-		}
-	}
-	return NULL;
-}
-
-// overloaded to additionally move data to/from the webserver
-void LLHTTPAssetStorage::checkForTimeouts()
-{
-	CURLMcode mcode;
-	LLAssetRequest *req;
-	while ( (req = findNextRequest(mPendingDownloads, mRunningDownloads)) )
-	{
-		// Setup this curl download request
-		// We need to generate a new request here
-		// since the one in the list could go away
-		std::string tmp_url;
-		std::string uuid_str;
-		req->getUUID().toString(uuid_str);
-		std::string base_url = getBaseURL(req->getUUID(), req->getType());
-		tmp_url = llformat("%s/%36s.%s", base_url.c_str() , uuid_str.c_str(), LLAssetType::lookup(req->getType()));
-
-		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
-										req->getType(), RT_DOWNLOAD, tmp_url, mCurlMultiHandle);
-		new_req->mTmpUUID.generate();
-
-		// Sets pending download flag internally
-		new_req->setupCurlHandle();
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &curlDownCallback);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEDATA, new_req->mCurlHandle);
-	
-		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
-		if (mcode > CURLM_OK)
-		{
-			// Failure.  Deleting the pending request will remove it from the running
-			// queue, and push it to the end of the pending queue.
-			new_req->cleanupCurlHandle();
-			deletePendingRequest(RT_DOWNLOAD, new_req->getType(), new_req->getUUID());
-			break;
-		}
-		else
-		{
-			LL_INFOS() << "Requesting " << new_req->mURLBuffer << LL_ENDL;
-		}
-	}
-
-	while ( (req = findNextRequest(mPendingUploads, mRunningUploads)) )
-	{
-		// setup this curl upload request
-
-		bool do_compress = req->getType() == LLAssetType::AT_OBJECT;
-
-		std::string tmp_url;
-		std::string uuid_str;
-		req->getUUID().toString(uuid_str);
-		tmp_url = mBaseURL + "/" + uuid_str + "." + LLAssetType::lookup(req->getType());
-		if (do_compress) tmp_url += ".gz";
-
-		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
-									req->getType(), RT_UPLOAD, tmp_url, mCurlMultiHandle);
-
-		if (req->mIsUserWaiting) //If a user is waiting on a realtime response, we want to perserve information across upload attempts.
-		{
-			new_req->mTime          = req->mTime;
-			new_req->mTimeout       = req->mTimeout;
-			new_req->mIsUserWaiting = req->mIsUserWaiting;
-		}
-
-		if (do_compress)
-		{
-			new_req->prepareCompressedUpload();
-		}
-
-		// Sets pending upload flag internally
-		new_req->setupCurlHandle();
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_UPLOAD, 1);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback);
-
-		if (do_compress)
-		{
-			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION,
-					&LLHTTPAssetRequest::curlCompressedUploadCallback);
-		}
-		else
-		{
-			LLVFile file(mVFS, req->getUUID(), req->getType());
-			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize());
-			curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION,
-					&curlUpCallback);
-		}
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle);
-	
-		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
-		if (mcode > CURLM_OK)
-		{
-			// Failure.  Deleting the pending request will remove it from the running
-			// queue, and push it to the end of the pending queue.
-			new_req->cleanupCurlHandle();
-			deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());
-			break;
-		}
-		else
-		{
-			// Get the uncompressed file size.
-			LLVFile file(mVFS,new_req->getUUID(),new_req->getType());
-			S32 size = file.getSize();
-			LL_INFOS() << "Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << LL_ENDL;
-			if (size == 0)
-			{
-				LL_WARNS() << "Rejecting zero size PUT request!" << LL_ENDL;
-				new_req->cleanupCurlHandle();
-				deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());				
-			}
-		}
-		// Pending upload will have been flagged by the request
-	}
-
-	while ( (req = findNextRequest(mPendingLocalUploads, mRunningLocalUploads)) )
-	{
-		// setup this curl upload request
-		LLVFile file(mVFS, req->getUUID(), req->getType());
-
-		std::string tmp_url;
-		std::string uuid_str;
-		req->getUUID().toString(uuid_str);
-		
-		// KLW - All temporary uploads are saved locally "http://localhost:12041/asset"
-		tmp_url = llformat("%s/%36s.%s", mLocalBaseURL.c_str(), uuid_str.c_str(), LLAssetType::lookup(req->getType()));
-
-		LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), 
-										req->getType(), RT_LOCALUPLOAD, tmp_url, mCurlMultiHandle);
-		new_req->mRequestingAgentID = req->mRequestingAgentID;
-
-		// Sets pending upload flag internally
-		new_req->setupCurlHandle();
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_PUT, 1);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize());
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, &curlUpCallback);
-		curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle);
-	
-		mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle);
-		if (mcode > CURLM_OK)
-		{
-			// Failure.  Deleting the pending request will remove it from the running
-			// queue, and push it to the end of the pending queue.
-			new_req->cleanupCurlHandle();
-			deletePendingRequest(RT_LOCALUPLOAD, new_req->getType(), new_req->getUUID());
-			break;
-		}
-		else
-		{
-			// Get the uncompressed file size.
-			S32 size = file.getSize();
-
-			LL_INFOS() << "TAT: LLHTTPAssetStorage::checkForTimeouts() : pending local!"
-				<< " Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << LL_ENDL;
-			if (size == 0)
-			{
-				
-				LL_WARNS() << "Rejecting zero size PUT request!" << LL_ENDL;
-				new_req->cleanupCurlHandle();
-				deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID());				
-			}
-
-		}
-		// Pending upload will have been flagged by the request
-	}
-	S32 count = 0;
-	int queue_length;
-	do
-	{
-		mcode = curl_multi_perform(mCurlMultiHandle, &queue_length);
-		count++;
-	} while (mcode == CURLM_CALL_MULTI_PERFORM && (count < 5));
-
-	CURLMsg *curl_msg;
-	do
-	{
-		curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length);
-		if (curl_msg && curl_msg->msg == CURLMSG_DONE)
-		{
-			long curl_result = 0;
-			S32 xfer_result = LL_ERR_NOERR;
-
-			LLHTTPAssetRequest *req = NULL;
-			curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_PRIVATE, &req);
-								
-			// TODO: Throw curl_result at all callbacks.
-			curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result);
-			if (RT_UPLOAD == req->mRequestType || RT_LOCALUPLOAD == req->mRequestType)
-			{
-				if (curl_msg->data.result == CURLE_OK && 
-					(   curl_result == HTTP_OK 
-					 || curl_result == HTTP_CREATED
-					 || curl_result == HTTP_NO_CONTENT))
-				{
-					LL_INFOS() << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << LL_ENDL;
-					if (RT_LOCALUPLOAD == req->mRequestType)
-					{
-						addTempAssetData(req->getUUID(), req->mRequestingAgentID, mHostName);
-					}
-				}
-				else if (curl_msg->data.result == CURLE_COULDNT_CONNECT ||
-						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_BAD_GATEWAY ||
-						curl_result == HTTP_SERVICE_UNAVAILABLE)
-				{
-					LL_WARNS() << "Re-requesting upload for " << req->getUUID() << ".  Received upload error to " << req->mURLBuffer <<
-						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
-
-					////HACK (probably) I am sick of this getting requeued and driving me mad.
-					//if (req->mIsUserWaiting)
-					//{
-					//	deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID());
-					//}
-				}
-				else
-				{
-					LL_WARNS() << "Failure uploading " << req->getUUID() << " to " << req->mURLBuffer <<
-						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
-
-					xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
-				}
-
-				if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT ||
-						curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
-						curl_result == HTTP_BAD_GATEWAY ||
-						curl_result == HTTP_SERVICE_UNAVAILABLE))
-				{
-					// shared upload finished callback
-					// in the base class, this is called from processUploadComplete
-					_callUploadCallbacks(req->getUUID(), req->getType(), (xfer_result == 0), LL_EXSTAT_CURL_RESULT | curl_result);
-					// Pending upload flag will get cleared when the request is deleted
-				}
-			}
-			else if (RT_DOWNLOAD == req->mRequestType)
-			{
-				if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK)
-				{
-					if (req->mVFile && req->mVFile->getSize() > 0)
-					{					
-						LL_INFOS() << "Success downloading " << req->mURLBuffer << ", size " << req->mVFile->getSize() << LL_ENDL;
-
-						req->mVFile->rename(req->getUUID(), req->getType());
-					}
-					else
-					{
-						// *TODO: if this actually indicates a bad asset on the server
-						// (not certain at this point), then delete it
-						LL_WARNS() << "Found " << req->mURLBuffer << " to be zero size" << LL_ENDL;
-						xfer_result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
-					}
-				}
-				else
-				{
-					// KLW - TAT See if an avatar owns this texture, and if so request re-upload.
-					LL_WARNS() << "Failure downloading " << req->mURLBuffer << 
-						" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
-
-					xfer_result = (curl_result == HTTP_NOT_FOUND) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
-
-					if (req->mVFile)
-					{
-						req->mVFile->remove();
-					}
-				}
-
-				// call the static callback for transfer completion
-				// this will cleanup all requests for this asset, including ours
-				downloadCompleteCallback(
-					xfer_result,
-					req->getUUID(),
-					req->getType(),
-					(void *)req,
-					LL_EXSTAT_CURL_RESULT | curl_result);
-				// Pending download flag will get cleared when the request is deleted
-			}
-			else
-			{
-				// nothing, just axe this request
-				// currently this can only mean an asset delete
-			}
-
-			// Deleting clears the pending upload/download flag if it's set and the request is transferring
-			delete req;
-			req = NULL;
-		}
-
-	} while (curl_msg && queue_length > 0);
-	
-
-	// Cleanup 
-	// We want to bump to the back of the line any running uploads that have timed out.
-	bumpTimedOutUploads();
-
-	LLAssetStorage::checkForTimeouts();
-}
-
-void LLHTTPAssetStorage::bumpTimedOutUploads()
-{
-	bool user_waiting=FALSE;
-
-	F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
-
-	if (mPendingUploads.size())
-	{
-		request_list_t::iterator it = mPendingUploads.begin();
-		LLAssetRequest* req = *it;
-		user_waiting=req->mIsUserWaiting;
-	}
-
-	// No point bumping currently running uploads if there are no others in line.
-	if (!(mPendingUploads.size() > mRunningUploads.size()) && !user_waiting) 
-	{
-		return;
-	}
-
-	// deletePendingRequest will modify the mRunningUploads list so we don't want to iterate over it.
-	request_list_t temp_running = mRunningUploads;
-
-	request_list_t::iterator it = temp_running.begin();
-	request_list_t::iterator end = temp_running.end();
-	for ( ; it != end; ++it)
-	{
-		//request_list_t::iterator curiter = iter++;
-		LLAssetRequest* req = *it;
-
-		if ( req->mTimeout < (mt_secs - req->mTime) )
-		{
-			LL_WARNS() << "Asset upload request timed out for "
-					<< req->getUUID() << "."
-					<< LLAssetType::lookup(req->getType()) 
-					<< ", bumping to the back of the line!" << LL_ENDL;
-
-			deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID());
-		}
-	}
-}
-
-// static
-size_t LLHTTPAssetStorage::curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data)
-{
-	if (!gAssetStorage)
-	{
-		LL_WARNS() << "Missing gAssetStorage, aborting curl download callback!" << LL_ENDL;
-		return 0;
-	}
-	S32 bytes = (S32)(size * nmemb);
-	CURL *curl_handle = (CURL *)user_data;
-	LLHTTPAssetRequest *req = NULL;
-	curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req);
-
-	if (! req->mVFile)
-	{
-		req->mVFile = new LLVFile(gAssetStorage->mVFS, req->mTmpUUID, LLAssetType::AT_NONE, LLVFile::APPEND);
-	}
-
-	double content_length = 0.0;
-	curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
-
-	// sanitize content_length, reconcile w/ actual data
-	S32 file_length = llmax(0, (S32)llmin(content_length, 20000000.0), bytes + req->mVFile->getSize());
-
-	req->mVFile->setMaxSize(file_length);
-	req->mVFile->write((U8*)data, bytes);
-
-	return nmemb;
-}
-
-// static 
-size_t LLHTTPAssetStorage::curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data)
-{
-	if (!gAssetStorage)
-	{
-		LL_WARNS() << "Missing gAssetStorage, aborting curl download callback!" << LL_ENDL;
-		return 0;
-	}
-	CURL *curl_handle = (CURL *)user_data;
-	LLHTTPAssetRequest *req = NULL;
-	curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req);
-
-	if (! req->mVFile)
-	{
-		req->mVFile = new LLVFile(gAssetStorage->mVFS, req->getUUID(), req->getType(), LLVFile::READ);
-	}
-
-	S32 bytes = llmin((S32)(size * nmemb), (S32)(req->mVFile->getSize() - req->mVFile->tell()));
-
-	req->mVFile->read((U8*)data, bytes);/*Flawfinder: ignore*/
-
-	return req->mVFile->getLastBytesRead();
-}
-
-// static
-size_t LLHTTPAssetStorage::nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data)
-{
-	// do nothing, this is here to soak up script output so it doesn't end up on stdout
-
-	return nmemb;
-}
-
-
-
-// blocking asset fetch which bypasses the VFS
-// this is a very limited function for use by the simstate loader and other one-offs
-S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata)
-{
-	// *NOTE: There is no guarantee that the uuid and the asset_type match
-	// - not that it matters. - Doug
-	LL_DEBUGS() << "LLHTTPAssetStorage::getURLToFile() - " << url << LL_ENDL;
-
-	FILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
-	if (! fp)
-	{
-		LL_WARNS() << "Failed to open " << filename << " for writing" << LL_ENDL;
-		return LL_ERR_ASSET_REQUEST_FAILED;
-	}
-
-	// make sure we use the normal curl setup, even though we don't really need a request object
-	LLHTTPAssetRequest req(this, uuid, asset_type, RT_DOWNLOAD, url, mCurlMultiHandle);
-	req.mFP = fp;
-	
-	req.setupCurlHandle();
-	curl_easy_setopt(req.mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE);
-	curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEFUNCTION, &curlFileDownCallback);
-	curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEDATA, req.mCurlHandle);
-
-	curl_multi_add_handle(mCurlMultiHandle, req.mCurlHandle);
-	LL_INFOS() << "Requesting as file " << req.mURLBuffer << LL_ENDL;
-
-	// braindead curl loop
-	int queue_length;
-	CURLMsg *curl_msg;
-	LLTimer timeout;
-	timeout.setTimerExpirySec(GET_URL_TO_FILE_TIMEOUT);
-	bool success = false;
-	S32 xfer_result = 0;
-	do
-	{
-		curl_multi_perform(mCurlMultiHandle, &queue_length);
-		curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length);
-
-		if (callback)
-		{
-			callback(userdata);
-		}
-
-		if ( curl_msg && (CURLMSG_DONE == curl_msg->msg) )
-		{
-			success = true;
-		}
-		else if (timeout.hasExpired())
-		{
-			LL_WARNS() << "Request for " << url << " has timed out." << LL_ENDL;
-			success = false;
-			xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
-			break;
-		}
-	} while (!success);
-
-	if (success)
-	{
-		long curl_result = 0;
-		curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result);
-		
-		if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK)
-		{
-			S32 size = ftell(req.mFP);
-			if (size > 0)
-			{
-				// everything seems to be in order
-				LL_INFOS() << "Success downloading " << req.mURLBuffer << " to file, size " << size << LL_ENDL;
-			}
-			else
-			{
-				LL_WARNS() << "Found " << req.mURLBuffer << " to be zero size" << LL_ENDL;
-				xfer_result = LL_ERR_ASSET_REQUEST_FAILED;
-			}
-		}
-		else
-		{
-			xfer_result = curl_result == HTTP_NOT_FOUND ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
-			LL_INFOS() << "Failure downloading " << req.mURLBuffer << 
-				" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
-		}
-	}
-
-	fclose(fp);
-	if (xfer_result)
-	{
-		LLFile::remove(filename);
-	}
-	return xfer_result;
-}
-
-
-// static
-size_t LLHTTPAssetStorage::curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data)
-{	
-	CURL *curl_handle = (CURL *)user_data;
-	LLHTTPAssetRequest *req = NULL;
-	curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req);
-
-	if (! req->mFP)
-	{
-		LL_WARNS() << "Missing mFP, aborting curl file download callback!" << LL_ENDL;
-		return 0;
-	}
-
-	return fwrite(data, size, nmemb, req->mFP);
-}
-
-LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt)
-{
-	switch (rt)
-	{
-	case RT_DOWNLOAD:
-		return &mRunningDownloads;
-	case RT_UPLOAD:
-		return &mRunningUploads;
-	case RT_LOCALUPLOAD:
-		return &mRunningLocalUploads;
-	default:
-		return NULL;
-	}
-}
-
-const LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt) const
-{
-	switch (rt)
-	{
-	case RT_DOWNLOAD:
-		return &mRunningDownloads;
-	case RT_UPLOAD:
-		return &mRunningUploads;
-	case RT_LOCALUPLOAD:
-		return &mRunningLocalUploads;
-	default:
-		return NULL;
-	}
-}
-
-
-void LLHTTPAssetStorage::addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request)
-{
-	request_list_t* requests = getRunningList(rt);
-	if (requests)
-	{
-		requests->push_back(request);
-	}
-	else
-	{
-		LL_ERRS() << "LLHTTPAssetStorage::addRunningRequest - Request is not an upload OR download, this is bad!" << LL_ENDL;
-	}
-}
-
-void LLHTTPAssetStorage::removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request)
-{
-	request_list_t* requests = getRunningList(rt);
-	if (requests)
-	{
-		requests->remove(request);
-	}
-	else
-	{
-		LL_ERRS() << "LLHTTPAssetStorage::removeRunningRequest - Destroyed request is not an upload OR download, this is bad!" << LL_ENDL;
-	}
-}
-
-// virtual 
-void LLHTTPAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name)
-{
-	if (agent_id.isNull() || asset_id.isNull())
-	{
-		LL_WARNS() << "TAT: addTempAssetData bad id's asset_id: " << asset_id << "  agent_id: " << agent_id << LL_ENDL;
-		return;
-	}
-
-	LLTempAssetData temp_asset_data;
-	temp_asset_data.mAssetID = asset_id;
-	temp_asset_data.mAgentID = agent_id;
-	temp_asset_data.mHostName = host_name;
-
-	mTempAssets[asset_id] = temp_asset_data;
-}
-
-// virtual
-BOOL LLHTTPAssetStorage::hasTempAssetData(const LLUUID& texture_id) const
-{
-	uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id);
-	BOOL found = (citer != mTempAssets.end());
-	return found;
-}
-
-// virtual
-std::string LLHTTPAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const
-{
-	uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id);
-	if (citer != mTempAssets.end())
-	{
-		return citer->second.mHostName;
-	}
-	else
-	{
-		return std::string();
-	}
-}
-
-// virtual 
-LLUUID LLHTTPAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const
-{
-	uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id);
-	if (citer != mTempAssets.end())
-	{
-		return citer->second.mAgentID;
-	}
-	else
-	{
-		return LLUUID::null;
-	}
-}
-
-// virtual 
-void LLHTTPAssetStorage::removeTempAssetData(const LLUUID& asset_id)
-{
-	mTempAssets.erase(asset_id);
-}
-
-// virtual 
-void LLHTTPAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id)
-{
-	uuid_tempdata_map::iterator it = mTempAssets.begin();
-	uuid_tempdata_map::iterator end = mTempAssets.end();
-
-	while (it != end)
-	{
-		const LLTempAssetData& asset_data = it->second;
-		if (asset_data.mAgentID == agent_id)
-		{
-			mTempAssets.erase(it++);
-		}
-		else
-		{
-			++it;
-		}
-	}
-}
-
-std::string LLHTTPAssetStorage::getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type)
-{
-	if (LLAssetType::AT_TEXTURE == asset_type)
-	{
-		uuid_tempdata_map::const_iterator citer = mTempAssets.find(asset_id);
-		if (citer != mTempAssets.end())
-		{
-			const std::string& host_name = citer->second.mHostName;
-			std::string url = llformat(LOCAL_ASSET_URL_FORMAT, host_name.c_str());
-			return url;
-		}
-	}
-
-	return mBaseURL;
-}
-
-void LLHTTPAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const
-{
-	uuid_tempdata_map::const_iterator it = mTempAssets.begin();
-	uuid_tempdata_map::const_iterator end = mTempAssets.end();
-	S32 count = 0;
-	for ( ; it != end; ++it)
-	{
-		const LLTempAssetData& temp_asset_data = it->second;
-		if (avatar_id.isNull()
-			|| avatar_id == temp_asset_data.mAgentID)
-		{
-			LL_INFOS() << "TAT: dump agent " << temp_asset_data.mAgentID
-				<< " texture " << temp_asset_data.mAssetID
-				<< " host " << temp_asset_data.mHostName
-				<< LL_ENDL;
-			count++;
-		}
-	}
-
-	if (avatar_id.isNull())
-	{
-		LL_INFOS() << "TAT: dumped " << count << " entries for all avatars" << LL_ENDL;
-	}
-	else
-	{
-		LL_INFOS() << "TAT: dumped " << count << " entries for avatar " << avatar_id << LL_ENDL;
-	}
-}
-
-void LLHTTPAssetStorage::clearTempAssetData()
-{
-	LL_INFOS() << "TAT: Clearing temp asset data map" << LL_ENDL;
-	mTempAssets.clear();
-}
diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h
deleted file mode 100755
index 783e95cac627bedf83d2946de83ab1e32dba4fe1..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpassetstorage.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/** 
- * @file llhttpassetstorage.h
- * @brief Class for loading asset data to/from an external source over http.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LLHTTPASSETSTORAGE_H
-#define LLHTTPASSETSTORAGE_H
-
-#include "llassetstorage.h"
-#include "curl/curl.h"
-
-class LLVFile;
-class LLHTTPAssetRequest;
-typedef void (*progress_callback)(void* userdata);
-
-struct LLTempAssetData;
-
-typedef std::map<LLUUID,LLTempAssetData> uuid_tempdata_map;
-
-class LLHTTPAssetStorage : public LLAssetStorage
-{
-public:
-	LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
-					   LLVFS *vfs, LLVFS *static_vfs,
-					   const LLHost &upstream_host,
-					   const std::string& web_host,
-					   const std::string& local_web_host,
-					   const std::string& host_name);
-
-	LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
-					   LLVFS *vfs, LLVFS *static_vfs,
-					   const std::string& web_host,
-					   const std::string& local_web_host,
-					   const std::string& host_name);
-
-
-	virtual ~LLHTTPAssetStorage();
-
-	using LLAssetStorage::storeAssetData; // Unhiding virtuals...
-
-	virtual void storeAssetData(
-		const LLUUID& uuid,
-		LLAssetType::EType atype,
-		LLStoreAssetCallback callback,
-		void* user_data,
-		bool temp_file = false,
-		bool is_priority = false,
-		bool store_local = false,
-		const LLUUID& requesting_agent_id = LLUUID::null,
-		bool user_waiting=FALSE,
-		F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
-
-	virtual void storeAssetData(
-		const std::string& filename,
-		const LLUUID& asset_id,
-		LLAssetType::EType atype,
-		LLStoreAssetCallback callback,
-		void* user_data,
-		bool temp_file,
-		bool is_priority,
-		bool user_waiting=FALSE,
-		F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
-
-	virtual LLSD getPendingDetails(ERequestType rt,
-	 				LLAssetType::EType asset_type,
-	 				const std::string& detail_prefix) const;
-
-	virtual LLSD getPendingRequest(ERequestType rt,
-							LLAssetType::EType asset_type,
-							const LLUUID& asset_id) const;
-
-	virtual bool deletePendingRequest(ERequestType rt,
-							LLAssetType::EType asset_type,
-							const LLUUID& asset_id);
-
-	// Hack.  One off curl download an URL to a file.  Probably should be elsewhere.
-	// Only used by lldynamicstate.  The API is broken, and should be replaced with
-	// a generic HTTP file fetch - Doug 9/25/06
-	S32 getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata);
-	
-	LLAssetRequest* findNextRequest(request_list_t& pending, request_list_t& running);
-
-	void checkForTimeouts();
-	
-	static size_t curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data);
-	static size_t curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data);
-	static size_t curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data);
-	static size_t nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data);
-
-	// Should only be used by the LLHTTPAssetRequest
-	void addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request);
-	void removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request);
-
-	request_list_t* getRunningList(ERequestType rt);
-	const request_list_t* getRunningList(ERequestType rt) const;
-
-	// Temp assets are stored on sim nodes, they have agent ID and location data associated with them.
-	virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name);
-	virtual BOOL hasTempAssetData(const LLUUID& texture_id) const;
-	virtual std::string getTempAssetHostName(const LLUUID& texture_id) const;
-	virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const;
-	virtual void removeTempAssetData(const LLUUID& asset_id);
-	virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id);
-
-	// Pass LLUUID::null for all
-	virtual void dumpTempAssetData(const LLUUID& avatar_id) const;
-	virtual void clearTempAssetData();
-
-protected:
-	void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
-						   void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
-						   void *user_data, BOOL duplicate, BOOL is_priority);
-
-private:
-	void _init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name);
-
-	// This will return the correct base URI for any http asset request
-	std::string getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type);
-
-	// Check for running uploads that have timed out
-	// Bump these to the back of the line to let other uploads complete.
-	void bumpTimedOutUploads();
-
-protected:
-	std::string		mBaseURL;
-	std::string		mLocalBaseURL;
-	std::string		mHostName;
-
-	CURLM  *mCurlMultiHandle;
-
-	request_list_t mRunningDownloads;
-	request_list_t mRunningUploads;
-	request_list_t mRunningLocalUploads;
-
-	uuid_tempdata_map mTempAssets;
-};
-
-#endif
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
deleted file mode 100755
index 60f17e68709cc9fa04433f971ca59b7fde0239e4..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpclient.cpp
+++ /dev/null
@@ -1,673 +0,0 @@
-/** 
- * @file llhttpclient.cpp
- * @brief Implementation of classes for making HTTP requests.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include <openssl/x509_vfy.h>
-#include "llhttpclient.h"
-
-#include "llassetstorage.h"
-#include "lliopipe.h"
-#include "llurlrequest.h"
-#include "llbufferstream.h"
-#include "llsdserialize.h"
-#include "llvfile.h"
-#include "llvfs.h"
-#include "lluri.h"
-
-#include "message.h"
-#include <curl/curl.h>
-
-
-const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
-LLURLRequest::SSLCertVerifyCallback LLHTTPClient::mCertVerifyCallback = NULL;
-
-////////////////////////////////////////////////////////////////////////////
-
-// Responder class moved to LLCurl
-
-namespace
-{
-	class LLHTTPClientURLAdaptor : public LLURLRequestComplete
-	{
-	public:
-		LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder)
-			: LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR),
-			  mReason("LLURLRequest complete w/no status")
-		{
-		}
-		
-		~LLHTTPClientURLAdaptor()
-		{
-		}
-
-		virtual void httpStatus(S32 status, const std::string& reason)
-		{
-			LLURLRequestComplete::httpStatus(status,reason);
-
-			mStatus = status;
-			mReason = reason;
-		}
-
-		virtual void complete(const LLChannelDescriptors& channels,
-							  const buffer_ptr_t& buffer)
-		{
-			// *TODO: Re-interpret mRequestStatus codes?
-			//        Would like to detect curl errors, such as
-			//        connection errors, write erros, etc.
-			if (mResponder.get())
-			{
-				mResponder->setResult(mStatus, mReason);
-				mResponder->completedRaw(channels, buffer);
-			}
-		}
-		virtual void header(const std::string& header, const std::string& value)
-		{
-			if (mResponder.get())
-			{
-				mResponder->setResponseHeader(header, value);
-			}
-		}
-
-	private:
-		LLCurl::ResponderPtr mResponder;
-		S32 mStatus;
-		std::string mReason;
-	};
-	
-	class Injector : public LLIOPipe
-	{
-	public:
-		virtual const std::string& contentType() = 0;
-	};
-
-	class LLSDInjector : public Injector
-	{
-	public:
-		LLSDInjector(const LLSD& sd) : mSD(sd) {}
-		virtual ~LLSDInjector() {}
-
-		const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; }
-
-		virtual EStatus process_impl(const LLChannelDescriptors& channels,
-			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
-		{
-			LLBufferStream ostream(channels, buffer.get());
-			LLSDSerialize::toXML(mSD, ostream);
-			eos = true;
-			return STATUS_DONE;
-		}
-
-		const LLSD mSD;
-	};
-
-	class RawInjector : public Injector
-	{
-	public:
-		RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
-		virtual ~RawInjector() {delete [] mData;}
-
-		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
-
-		virtual EStatus process_impl(const LLChannelDescriptors& channels,
-			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
-		{
-			LLBufferStream ostream(channels, buffer.get());
-			ostream.write((const char *)mData, mSize);  // hopefully chars are always U8s
-			eos = true;
-			return STATUS_DONE;
-		}
-
-		const U8* mData;
-		S32 mSize;
-	};
-	
-	class FileInjector : public Injector
-	{
-	public:
-		FileInjector(const std::string& filename) : mFilename(filename) {}
-		virtual ~FileInjector() {}
-
-		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
-
-		virtual EStatus process_impl(const LLChannelDescriptors& channels,
-			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
-		{
-			LLBufferStream ostream(channels, buffer.get());
-
-			llifstream fstream(mFilename.c_str(), std::iostream::binary | std::iostream::out);
-			if(fstream.is_open())
-			{
-				fstream.seekg(0, std::ios::end);
-				U32 fileSize = (U32)fstream.tellg();
-				fstream.seekg(0, std::ios::beg);
-				std::vector<char> fileBuffer(fileSize);
-				fstream.read(&fileBuffer[0], fileSize);
-				ostream.write(&fileBuffer[0], fileSize);
-				fstream.close();
-				eos = true;
-				return STATUS_DONE;
-			}
-			
-			return STATUS_ERROR;
-		}
-
-		const std::string mFilename;
-	};
-	
-	class VFileInjector : public Injector
-	{
-	public:
-		VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
-		virtual ~VFileInjector() {}
-
-		const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
-
-		virtual EStatus process_impl(const LLChannelDescriptors& channels,
-			buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
-		{
-			LLBufferStream ostream(channels, buffer.get());
-			
-			LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ);
-			S32 fileSize = vfile.getSize();
-			U8* fileBuffer;
-			fileBuffer = new U8 [fileSize];
-            vfile.read(fileBuffer, fileSize);
-            ostream.write((char*)fileBuffer, fileSize);
-			delete [] fileBuffer;
-			eos = true;
-			return STATUS_DONE;
-		}
-
-		const LLUUID mUUID;
-		LLAssetType::EType mAssetType;
-	};
-
-	
-	LLPumpIO* theClientPump = NULL;
-}
-
-void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback)
-{
-	LLHTTPClient::mCertVerifyCallback = callback;
-}
-
-static void request(
-	const std::string& url,
-	EHTTPMethod method,
-	Injector* body_injector,
-	LLCurl::ResponderPtr responder,
-	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
-	const LLSD& headers = LLSD(),
-	bool follow_redirects = true
-    )
-{
-	if (!LLHTTPClient::hasPump())
-	{
-		if (responder)
-		{
-			responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
-		}
-		delete body_injector;
-		return;
-	}
-	LLPumpIO::chain_t chain;
-
-	LLURLRequest* req = new LLURLRequest(method, url, follow_redirects);
-	if(!req->isValid())//failed
-	{
-		if (responder)
-		{
-			responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
-		}
-		delete req;
-		delete body_injector;
-		return;
-	}
-
-	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
-
-	LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
-
-	// Insert custom headers if the caller sent any
-	if (headers.isMap())
-	{
-		if (headers.has(HTTP_OUT_HEADER_COOKIE))
-		{
-			req->allowCookies();
-		}
-
-		LLSD::map_const_iterator iter = headers.beginMap();
-		LLSD::map_const_iterator end  = headers.endMap();
-
-		for (; iter != end; ++iter)
-		{
-			//if the header is "Pragma" with no value
-			//the caller intends to force libcurl to drop
-			//the Pragma header it so gratuitously inserts
-			//Before inserting the header, force libcurl
-			//to not use the proxy (read: llurlrequest.cpp)
-			if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
-			{
-				req->useProxy(false);
-			}
-			LL_DEBUGS("LLHTTPClient") << "header = " << iter->first 
-				<< ": " << iter->second.asString() << LL_ENDL;
-			req->addHeader(iter->first, iter->second.asString());
-		}
-	}
-
-	// Check to see if we have already set Accept or not. If no one
-	// set it, set it to application/llsd+xml since that's what we
-	// almost always want.
-	if( method != HTTP_PUT && method != HTTP_POST )
-	{
-		if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
-		{
-			req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
-		}
-	}
-
-	if (responder)
-	{
-		responder->setURL(url);
-		responder->setHTTPMethod(method);
-	}
-
-	req->setCallback(new LLHTTPClientURLAdaptor(responder));
-
-	if (method == HTTP_POST  &&  gMessageSystem)
-	{
-		req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
-					gMessageSystem->mPort));
-	}
-
-	if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
-	{
-		if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
-		{
-			// If the Content-Type header was passed in, it has
-			// already been added as a header through req->addHeader
-			// in the loop above. We defer to the caller's wisdom, but
-			// if they did not specify a Content-Type, then ask the
-			// injector.
-			req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
-		}
-		chain.push_back(LLIOPipe::ptr_t(body_injector));
-	}
-
-	chain.push_back(LLIOPipe::ptr_t(req));
-
-	theClientPump->addChain(chain, timeout);
-}
-
-
-void LLHTTPClient::getByteRange(
-	const std::string& url,
-	S32 offset,
-	S32 bytes,
-	ResponderPtr responder,
-	const LLSD& hdrs,
-	const F32 timeout,
-	bool follow_redirects /* = true */)
-{
-	LLSD headers = hdrs;
-	if(offset > 0 || bytes > 0)
-	{
-		std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
-		headers[HTTP_OUT_HEADER_RANGE] = range;
-	}
-    request(url,HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
-}
-
-void LLHTTPClient::head(
-	const std::string& url,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout,
-	bool follow_redirects /* = true */)
-{
-	request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
-}
-
-void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout,
-					   bool follow_redirects /* = true */)
-{
-	request(url, HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
-}
-void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers,
-								 const F32 timeout, bool follow_redirects /* = true */)
-{
-	request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
-}
-void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout,
-								 bool follow_redirects /* = true */)
-{
-	getHeaderOnly(url, responder, LLSD(), timeout, follow_redirects);
-}
-
-void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers,
-					   const F32 timeout, bool follow_redirects /* = true */)
-{
-	LLURI uri;
-	
-	uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
-	get(uri.asString(), responder, headers, timeout, follow_redirects);
-}
-
-// A simple class for managing data returned from a curl http request.
-class LLHTTPBuffer
-{
-public:
-	LLHTTPBuffer() { }
-
-	static size_t curl_write( void *ptr, size_t size, size_t nmemb, void *user_data)
-	{
-		LLHTTPBuffer* self = (LLHTTPBuffer*)user_data;
-		
-		size_t bytes = (size * nmemb);
-		self->mBuffer.append((char*)ptr,bytes);
-		return nmemb;
-	}
-
-	LLSD asLLSD()
-	{
-		LLSD content;
-
-		if (mBuffer.empty()) return content;
-		
-		std::istringstream istr(mBuffer);
-		LLSDSerialize::fromXML(content, istr);
-		return content;
-	}
-
-	const std::string& asString()
-	{
-		return mBuffer;
-	}
-
-private:
-	std::string mBuffer;
-};
-
-// These calls are blocking! This is usually bad, unless you're a dataserver. Then it's awesome.
-
-/**
-	@brief does a blocking request on the url, returning the data or bad status.
-
-	@param url URI to verb on.
-	@param method the verb to hit the URI with.
-	@param body the body of the call (if needed - for instance not used for GET and DELETE, but is for POST and PUT)
-	@param headers HTTP headers to use for the request.
-	@param timeout Curl timeout to use. Defaults to 5. Rationale:
-	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
-
-	@returns an LLSD map: {status: integer, body: map}
-  */
-static LLSD blocking_request(
-	const std::string& url,
-	EHTTPMethod method,
-	const LLSD& body,
-	const LLSD& headers = LLSD(),
-	const F32 timeout = 5
-)
-{
-	LL_DEBUGS() << "blockingRequest of " << url << LL_ENDL;
-	char curl_error_buffer[CURL_ERROR_SIZE] = "\0";
-	CURL* curlp = LLCurl::newEasyHandle();
-	llassert_always(curlp != NULL) ;
-
-	LLHTTPBuffer http_buffer;
-	std::string body_str;
-	
-	// other request method checks root cert first, we skip?
-
-	// Apply configured proxy settings
-	LLProxy::getInstance()->applyProxySettings(curlp);
-	
-	// * Set curl handle options
-	curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1);	// don't use SIGALRM for timeouts
-	curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout);	// seconds, see warning at top of function.
-	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());
-	curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer);
-
-	// * Setup headers (don't forget to free them after the call!)
-	curl_slist* headers_list = NULL;
-	if (headers.isMap())
-	{
-		LLSD::map_const_iterator iter = headers.beginMap();
-		LLSD::map_const_iterator end  = headers.endMap();
-		for (; iter != end; ++iter)
-		{
-			std::ostringstream header;
-			header << iter->first << ": " << iter->second.asString() ;
-			LL_DEBUGS() << "header = " << header.str() << LL_ENDL;
-			headers_list = curl_slist_append(headers_list, header.str().c_str());
-		}
-	}
-	
-	// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
-	if (method == HTTP_GET)
-	{
-		curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
-	}
-	else if (method == HTTP_POST)
-	{
-		curl_easy_setopt(curlp, CURLOPT_POST, 1);
-		//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
-		std::ostringstream ostr;
-		LLSDSerialize::toXML(body, ostr);
-		body_str = ostr.str();
-		curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
-		//copied from PHP libs, correct?
-		headers_list = curl_slist_append(headers_list, 
-				llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
-
-		// copied from llurlrequest.cpp
-		// it appears that apache2.2.3 or django in etch is busted. If
-		// we do not clear the expect header, we get a 500. May be
-		// limited to django/mod_wsgi.
-		headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str());
-	}
-	
-	// * Do the action using curl, handle results
-	LL_DEBUGS() << "HTTP body: " << body_str << LL_ENDL;
-	headers_list = curl_slist_append(headers_list,
-				llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
-	CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
-	if ( curl_result != CURLE_OK )
-	{
-		LL_INFOS() << "Curl is hosed - can't add headers" << LL_ENDL;
-	}
-
-	LLSD response = LLSD::emptyMap();
-	S32 curl_success = curl_easy_perform(curlp);
-	S32 http_status = HTTP_INTERNAL_ERROR;
-	curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
-	response["status"] = http_status;
-	// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
-	if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) )
-	{
-		// We expect 404s, don't spam for them.
-		LL_WARNS() << "CURL REQ URL: " << url << LL_ENDL;
-		LL_WARNS() << "CURL REQ METHOD TYPE: " << method << LL_ENDL;
-		LL_WARNS() << "CURL REQ HEADERS: " << headers.asString() << LL_ENDL;
-		LL_WARNS() << "CURL REQ BODY: " << body_str << LL_ENDL;
-		LL_WARNS() << "CURL HTTP_STATUS: " << http_status << LL_ENDL;
-		LL_WARNS() << "CURL ERROR: " << curl_error_buffer << LL_ENDL;
-		LL_WARNS() << "CURL ERROR BODY: " << http_buffer.asString() << LL_ENDL;
-		response["body"] = http_buffer.asString();
-	}
-	else
-	{
-		response["body"] = http_buffer.asLLSD();
-		LL_DEBUGS() << "CURL response: " << http_buffer.asString() << LL_ENDL;
-	}
-	
-	if(headers_list)
-	{	// free the header list  
-		curl_slist_free_all(headers_list); 
-	}
-
-	// * Cleanup
-	LLCurl::deleteEasyHandle(curlp);
-	return response;
-}
-
-LLSD LLHTTPClient::blockingGet(const std::string& url)
-{
-	return blocking_request(url, HTTP_GET, LLSD());
-}
-
-LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
-{
-	return blocking_request(url, HTTP_POST, body);
-}
-
-void LLHTTPClient::put(
-	const std::string& url,
-	const LLSD& body,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
-}
-
-void LLHTTPClient::patch(
-	const std::string& url,
-	const LLSD& body,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers);
-}
-
-void LLHTTPClient::putRaw(
-    const std::string& url,
-    const U8* data,
-    S32 size,
-    ResponderPtr responder,
-    const LLSD& headers,
-    const F32 timeout)
-{
-	request(url, HTTP_PUT, new RawInjector(data, size), responder, timeout, headers);
-}
-
-void LLHTTPClient::post(
-	const std::string& url,
-	const LLSD& body,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
-}
-
-void LLHTTPClient::postRaw(
-	const std::string& url,
-	const U8* data,
-	S32 size,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
-}
-
-void LLHTTPClient::postFile(
-	const std::string& url,
-	const std::string& filename,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers);
-}
-
-void LLHTTPClient::postFile(
-	const std::string& url,
-	const LLUUID& uuid,
-	LLAssetType::EType asset_type,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
-}
-
-// static
-void LLHTTPClient::del(
-	const std::string& url,
-	ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	request(url, HTTP_DELETE, NULL, responder, timeout, headers);
-}
-
-// static
-void LLHTTPClient::move(
-	const std::string& url,
-	const std::string& destination,
-	ResponderPtr responder,
-	const LLSD& hdrs,
-	const F32 timeout)
-{
-	LLSD headers = hdrs;
-	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
-	request(url, HTTP_MOVE, NULL, responder, timeout, headers);
-}
-
-// static
-void LLHTTPClient::copy(
-	const std::string& url,
-	const std::string& destination,
-	ResponderPtr responder,
-	const LLSD& hdrs,
-	const F32 timeout)
-{
-	LLSD headers = hdrs;
-	headers[HTTP_OUT_HEADER_DESTINATION] = destination;
-	request(url, HTTP_COPY, NULL, responder, timeout, headers);
-}
-
-
-void LLHTTPClient::setPump(LLPumpIO& pump)
-{
-	theClientPump = &pump;
-}
-
-bool LLHTTPClient::hasPump()
-{
-	return theClientPump != NULL;
-}
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
deleted file mode 100755
index fd48b4a743e3f4523d72488b0f5b91d7e89af326..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpclient.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/** 
- * @file llhttpclient.h
- * @brief Declaration of classes for making HTTP client requests.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLHTTPCLIENT_H
-#define LL_LLHTTPCLIENT_H
-
-/**
- * These classes represent the HTTP client framework.
- */
-
-#include <string>
-
-#include <boost/intrusive_ptr.hpp>
-#include <openssl/x509_vfy.h>
-#include "llurlrequest.h"
-#include "llassettype.h"
-#include "llcurl.h"
-#include "lliopipe.h"
-
-extern const F32 HTTP_REQUEST_EXPIRY_SECS;
-
-class LLUUID;
-class LLPumpIO;
-class LLSD;
-
-
-class LLHTTPClient
-{
-public:
-	// class Responder moved to LLCurl
-
-	// For convenience
-	typedef LLCurl::Responder Responder;
-	typedef LLCurl::ResponderPtr ResponderPtr;
-
-	
-	/** @name non-blocking API */
-	//@{
-	static void head(
-		const std::string& url,
-		ResponderPtr,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
-		bool follow_redirects = true);
-	static void getByteRange(const std::string& url, S32 offset, S32 bytes, ResponderPtr,
-							 const LLSD& headers=LLSD(), const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
-							 bool follow_redirects = true);
-	static void get(const std::string& url, ResponderPtr, const LLSD& headers = LLSD(),
-					const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
-	static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers = LLSD(),
-					const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
-
-	static void put(
-		const std::string& url,
-		const LLSD& body,
-		ResponderPtr,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-	static void putRaw(
-        const std::string& url,
-        const U8* data,
-        S32 size,
-        ResponderPtr responder,
-        const LLSD& headers = LLSD(),
-        const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-    
-
-	static void patch(
-		const std::string& url,
-		const LLSD& body,
-		ResponderPtr,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-
-	static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
-							  bool follow_redirects = true);
-	static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers,
-							  const F32 timeout=HTTP_REQUEST_EXPIRY_SECS, bool follow_redirects = true);
-
-	static void post(
-		const std::string& url,
-		const LLSD& body,
-		ResponderPtr,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-	/** Takes ownership of data and deletes it when sent */
-	static void postRaw(
-		const std::string& url,
-		const U8* data,
-		S32 size,
-		ResponderPtr responder,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-	static void postFile(
-		const std::string& url,
-		const std::string& filename,
-		ResponderPtr,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-	static void postFile(
-		const std::string& url,
-		const LLUUID& uuid,
-		LLAssetType::EType asset_type,
-		ResponderPtr responder,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-
-	static void del(
-		const std::string& url,
-		ResponderPtr responder,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-		///< sends a DELETE method, but we can't call it delete in c++
-
-	/**
-	 * @brief Send a MOVE webdav method
-	 *
-	 * @param url The complete serialized (and escaped) url to get.
-	 * @param destination The complete serialized destination url.
-	 * @param responder The responder that will handle the result.
-	 * @param headers A map of key:value headers to pass to the request
-	 * @param timeout The number of seconds to give the server to respond.
-	 */
-	static void move(
-		const std::string& url,
-		const std::string& destination,
-		ResponderPtr responder,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-
-	/**
-	 * @brief Send a COPY webdav method
-	 *
-	 * @param url The complete serialized (and escaped) url to get.
-	 * @param destination The complete serialized destination url.
-	 * @param responder The responder that will handle the result.
-	 * @param headers A map of key:value headers to pass to the request
-	 * @param timeout The number of seconds to give the server to respond.
-	 */
-	static void copy(
-		const std::string& url,
-		const std::string& destination,
-		ResponderPtr responder,
-		const LLSD& headers = LLSD(),
-		const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
-
-	//@}
-
-	/**
-	 * @brief Blocking HTTP get that returns an LLSD map of status and body.
-	 *
-	 * @param url the complete serialized (and escaped) url to get
-	 * @return An LLSD of { 'status':status, 'body':payload }
-	 */
-	static LLSD blockingGet(const std::string& url);
-
-	/**
-	 * @brief Blocking HTTP POST that returns an LLSD map of status and body.
-	 *
-	 * @param url the complete serialized (and escaped) url to get
-	 * @param body the LLSD post body
-	 * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
-	 */
-	static LLSD blockingPost(const std::string& url, const LLSD& body);
-
-	
-	static void setPump(LLPumpIO& pump);
-		///< must be called before any of the above calls are made
-	static bool hasPump();
-
-	static void setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback);
-	static  LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; }
-
-protected:
-	static LLURLRequest::SSLCertVerifyCallback mCertVerifyCallback;
-};
-
-#endif // LL_LLHTTPCLIENT_H
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
deleted file mode 100755
index b56a804f9422ad5a475d2fbd051a6c801e36dc0d..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/** 
- * @file llhttpclientadapter.cpp
- * @brief 
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llhttpclientadapter.h"
-#include "llhttpclient.h"
-
-LLHTTPClientAdapter::~LLHTTPClientAdapter() 
-{
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder) 
-{
-	LLSD empty_pragma_header;
-	// Pragma is required to stop curl adding "no-cache"
-	// Space is required to stop llurlrequest from turning off proxying
-	empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " "; 
-	LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
-{
-	LLSD empty_pragma_header = headers;
-	if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
-	{
-		// as above
-		empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
-	}
-	LLHTTPClient::get(url, responder, empty_pragma_header);
-}
-
-void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) 
-{
-	LLHTTPClient::put(url, body, responder);
-}
-
-void LLHTTPClientAdapter::put(
-		const std::string& url,
-		const LLSD& body,
-		LLCurl::ResponderPtr responder,
-		const LLSD& headers)
-{
-	LLHTTPClient::put(url, body, responder, headers);
-}
-
-void LLHTTPClientAdapter::del(
-	const std::string& url,
-	LLCurl::ResponderPtr responder)
-{
-	LLHTTPClient::del(url, responder);
-}
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
deleted file mode 100755
index 270282c66fb43ed6ee2a516d7572e744e226e6ed..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpclientadapter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/** 
- * @file llhttpclientadepter.h
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTPCLIENTADAPTER_H
-#define LL_HTTPCLIENTADAPTER_H
-
-#include "llhttpclientinterface.h"
-#include "llsingleton.h"	// LLSingleton<>
-
-class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton<LLHTTPClientAdapter>
-{
-public:
-	virtual ~LLHTTPClientAdapter();
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
-	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
-	virtual void put(
-		const std::string& url,
-		const LLSD& body,
-		LLCurl::ResponderPtr responder,
-		const LLSD& headers);
-	virtual void del(
-		const std::string& url,
-		LLCurl::ResponderPtr responder);
-};
-
-#endif
-
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
deleted file mode 100755
index 12a3857a61d4fa2bbec60779384a092a815dd1ac..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpclientinterface.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/** 
- * @file llhttpclientinterface.h
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLHTTPCLIENTINTERFACE_H
-#define LL_LLHTTPCLIENTINTERFACE_H
-
-#include "linden_common.h"
-#include "llcurl.h"
-
-#include <string>
-
-class LLHTTPClientInterface
-{
-public:
-	virtual ~LLHTTPClientInterface() {}
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder) = 0;
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) = 0;
-	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) = 0;
-};
-
-#endif // LL_LLHTTPCLIENTINTERFACE_H
-
diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d99bdd3f667b4921d1a4e6b248cee3fb3d85101a
--- /dev/null
+++ b/indra/llmessage/llhttpsdhandler.cpp
@@ -0,0 +1,105 @@
+/**
+* @file llhttpsdhandler.h
+* @brief Public-facing declarations for the HttpHandler class
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+#include "llhttpconstants.h"
+
+#include "llhttpsdhandler.h"
+#include "httpresponse.h"
+#include "httpheaders.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "bufferstream.h"
+#include "llcorehttputil.h"
+
+//========================================================================
+LLHttpSDHandler::LLHttpSDHandler(bool selfDelete):
+    mSelfDelete(selfDelete)
+{
+}
+
+void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+	LLCore::HttpStatus status = response->getStatus();
+
+	if (!status)
+	{
+		this->onFailure(response, status);
+	}
+	else
+	{
+		LLSD resplsd;
+		const bool emit_parse_errors = false;
+
+		bool parsed = !((response->getBodySize() == 0) ||
+			!LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, resplsd));
+
+		if (!parsed) 
+		{
+			// Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+			LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+			const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+
+			if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+			{
+				std::string thebody = LLCoreHttpUtil::responseToString(response);
+
+				LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+					<< " body: " << thebody << LL_ENDL;
+			}
+		}
+
+		this->onSuccess(response, resplsd);
+	}
+
+	// The handler must destroy itself when it is done. 
+	// *TODO: I'm not fond of this pattern. A class shooting itself in the head 
+	// outside of a smart pointer always makes me nervous.
+    if (mSelfDelete)
+    	delete this;
+}
+
+//========================================================================
+LLHttpSDGenericHandler::LLHttpSDGenericHandler(const std::string &name, bool selfDelete):
+	LLHttpSDHandler(selfDelete),
+	mName(name)
+{
+}
+
+void LLHttpSDGenericHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
+{
+	LL_DEBUGS() << mName << " Success." << LL_ENDL;
+}
+
+void LLHttpSDGenericHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
+{
+	LL_WARNS()
+		<< "\n--------------------------------------------------------------------------\n"
+		<< mName << " Error[" << status.toULong() << "] cannot access cap with url '" 
+		<< response->getRequestURL() << "' because " << status.toString()
+		<< "\n--------------------------------------------------------------------------"
+		<< LL_ENDL;
+}
diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b81dc66b9652ac995b61f2ced604c72639eb77f
--- /dev/null
+++ b/indra/llmessage/llhttpsdhandler.h
@@ -0,0 +1,72 @@
+/**
+* @file llhttpsdhandler.h
+* @brief Public-facing declarations for the HttpHandler class
+*
+* $LicenseInfo:firstyear=2012&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2012, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef	_LLHTTPSDHANDLER_H_
+#define	_LLHTTPSDHANDLER_H_
+#include "httpcommon.h"
+#include "httphandler.h"
+#include "lluri.h"
+
+/// Handler class LLCore's HTTP library. Splitting with separate success and 
+/// failure routines and parsing the result body into LLSD on success.  It 
+/// is intended to be subclassed for specific capability handling.
+/// 
+// *TODO: This class self deletes at the end of onCompleted method.  This is 
+// less than ideal and should be revisited.
+class LLHttpSDHandler : public LLCore::HttpHandler //,
+//    public std::enable_shared_from_this<LLHttpSDHandler>
+{
+public:
+
+	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+	
+protected:
+    LLHttpSDHandler(bool selfDelete = true);
+
+	virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0;
+	virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
+
+private:
+    bool mSelfDelete;
+
+};
+
+/// A trivial implementation of LLHttpSDHandler. This success and failure 
+/// methods log the action taken, the URI accessed and the status code returned 
+/// in the response.
+class LLHttpSDGenericHandler : public LLHttpSDHandler
+{
+public: 
+	LLHttpSDGenericHandler(const std::string &name, bool selfDelete = true);
+
+protected:
+	virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+	virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
+
+private:
+	std::string mName;
+};
+#endif
diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp
deleted file mode 100755
index 5363088d794cc80062d6eca530373ad78d11b6b9..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpsender.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/** 
- * @file llhttpsender.cpp
- * @brief Abstracts details of sending messages via HTTP.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#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;
-	static LLPointer<LLHTTPSender> defaultSender(new LLHTTPSender());
-}
-
-//virtual 
-LLHTTPSender::~LLHTTPSender()
-{
-}
-
-//virtual 
-void LLHTTPSender::send(const LLHost& host, const std::string& 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;
-	LL_INFOS() << "LLHTTPSender::send: POST to " << stream.str() << LL_ENDL;
-	LLHTTPClient::post(stream.str(), body, response);
-}
-
-//static 
-void LLHTTPSender::setSender(const LLHost& host, LLHTTPSender* sender)
-{
-	LL_INFOS() << "LLHTTPSender::setSender " << host << LL_ENDL;
-	senderMap[host] = sender;
-}
-
-//static
-const LLHTTPSender& LLHTTPSender::getSender(const LLHost& host)
-{
-	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);
-	}
-}
-
-//static 
-void LLHTTPSender::setDefaultSender(LLHTTPSender* sender)
-{
-	defaultSender = sender;
-}
diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h
deleted file mode 100755
index ff8fa2f95b16fbfddb136227489118cefd52f4d9..0000000000000000000000000000000000000000
--- a/indra/llmessage/llhttpsender.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/** 
- * @file llhttpsender.h
- * @brief Abstracts details of sending messages via HTTP.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTP_SENDER_H
-#define LL_HTTP_SENDER_H
-
-#include "llhttpclient.h"
-
-class LLHost;
-class LLSD;
-
-class LLHTTPSender : public LLThreadSafeRefCount
-{
- public:
-
-	virtual ~LLHTTPSender();
-
-	/** @brief Send message to host with body, call response when done */ 
-	virtual void send(const LLHost& host, 
-					  const std::string& 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);
-
-	/** @brief Set default sender, takes ownership of sender. */
-	static void setDefaultSender(LLHTTPSender* sender);
-};
-
-#endif // LL_HTTP_SENDER_H
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index 9b8d19cc3e2e0c0f1f8af2b985bae1686a85415a..537efa69d88bb1bdaf33b31fb0f0a814f7a18ca3 100755
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -30,9 +30,8 @@
 
 #include <string>
 #include <curl/curl.h>
-
+#include "httpcommon.h"
 #include "llapr.h"
-#include "llcurl.h"
 #include "llhost.h"
 
 // Static class variable instances
@@ -408,16 +407,6 @@ void LLProxy::cleanupClass()
 	deleteSingleton();
 }
 
-void LLProxy::applyProxySettings(LLCurlEasyRequest* handle)
-{
-	applyProxySettings(handle->getEasy());
-}
-
-void LLProxy::applyProxySettings(LLCurl::Easy* handle)
-{
-	applyProxySettings(handle->getCurlHandle());
-}
-
 /**
  * @brief Apply proxy settings to a CuRL request if an HTTP proxy is enabled.
  *
@@ -439,21 +428,21 @@ void LLProxy::applyProxySettings(CURL* handle)
 		// Now test again to verify that the proxy wasn't disabled between the first check and the lock.
 		if (mHTTPProxyEnabled)
 		{
-			LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()));
-			LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()));
+            LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY);
+            LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()), CURLOPT_PROXYPORT);
 
 			if (mProxyType == LLPROXY_SOCKS)
 			{
-				LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5));
+                LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);
 				if (mAuthMethodSelected == METHOD_PASSWORD)
 				{
 					std::string auth_string = mSocksUsername + ":" + mSocksPassword;
-					LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()));
+                    LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);
 				}
 			}
 			else
 			{
-				LLCurlFF::check_easy_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP));
+                LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);
 			}
 		}
 	}
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index a9193705404ace5c51168c261d5c9a35bb951f5a..bd23dd39defcb644ba2d904fd9c9748cf3d8c7ca 100755
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -27,12 +27,12 @@
 #ifndef LL_PROXY_H
 #define LL_PROXY_H
 
-#include "llcurl.h"
 #include "llhost.h"
 #include "lliosocket.h"
 #include "llmemory.h"
 #include "llsingleton.h"
 #include "llthread.h"
+#include <curl/curl.h>
 #include <string>
 
 // SOCKS error codes returned from the StartProxy method
@@ -208,16 +208,13 @@ enum LLSocks5AuthType
  * thread-safe method to apply those options to a curl request
  * (LLProxy::applyProxySettings()). This method is overloaded
  * to accommodate the various abstraction libcurl layers that exist
- * throughout the viewer (LLCurlEasyRequest, LLCurl::Easy, and CURL).
- *
- * If you are working with LLCurl or LLCurlEasyRequest objects,
- * the configured proxy settings will be applied in the constructors
- * of those request handles.  If you are working with CURL objects
- * directly, you will need to pass the handle of the request to
- * applyProxySettings() before issuing the request.
+ * throughout the viewer (CURL).
  *
  * To ensure thread safety, all LLProxy members that relate to the HTTP
  * proxy require the LLProxyMutex to be locked before accessing.
+ * 
+ * *TODO$: This should be moved into the LLCore::Http space.
+ * 
  */
 class LLProxy: public LLSingleton<LLProxy>
 {
@@ -252,9 +249,6 @@ class LLProxy: public LLSingleton<LLProxy>
 	// Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
 	// Safe to call from any thread.
 	void applyProxySettings(CURL* handle);
-	void applyProxySettings(LLCurl::Easy* handle);
-	void applyProxySettings(LLCurlEasyRequest* handle);
-
 	// Start a connection to the SOCKS 5 proxy. Call from main thread only.
 	S32 startSOCKSProxy(LLHost host);
 
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
deleted file mode 100755
index 61fcc5dd2f1791bc5816e7ece4a7104bfd47f2b1..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdmessage.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file   llsdmessage.cpp
- * @author Nat Goodspeed
- * @date   2008-10-31
- * @brief  Implementation for llsdmessage.
- * 
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if LL_WINDOWS
-#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
-#endif
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llsdmessage.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-#include "llevents.h"
-#include "llsdserialize.h"
-#include "llhttpclient.h"
-#include "llmessageconfig.h"
-#include "llhost.h"
-#include "message.h"
-#include "llsdutil.h"
-
-// Declare a static LLSDMessage instance to ensure that we have a listener as
-// soon as someone tries to post on our canonical LLEventPump name.
-static LLSDMessage httpListener;
-
-LLSDMessage::LLSDMessage():
-    // Instantiating our own local LLEventPump with a string name the
-    // constructor is NOT allowed to tweak is a way of ensuring Singleton
-    // semantics: attempting to instantiate a second LLSDMessage object would
-    // throw LLEventPump::DupPumpName.
-    mEventPump("LLHTTPClient")
-{
-    mEventPump.listen("self", boost::bind(&LLSDMessage::httpListener, this, _1));
-}
-
-bool LLSDMessage::httpListener(const LLSD& request)
-{
-    // Extract what we want from the request object. We do it all up front
-    // partly to document what we expect.
-    LLSD::String url(request["url"]);
-    LLSD payload(request["payload"]);
-    LLSD::String reply(request["reply"]);
-    LLSD::String error(request["error"]);
-    LLSD::Real timeout(request["timeout"]);
-    // If the LLSD doesn't even have a "url" key, we doubt it was intended for
-    // this listener.
-    if (url.empty())
-    {
-        std::ostringstream out;
-        out << "request event without 'url' key to '" << mEventPump.getName() << "'";
-        throw ArgError(out.str());
-    }
-    // Establish default timeout. This test relies on LLSD::asReal() returning
-    // exactly 0.0 for an undef value.
-    if (! timeout)
-    {
-        timeout = HTTP_REQUEST_EXPIRY_SECS;
-    }
-    LLHTTPClient::post(url, payload,
-                       new LLSDMessage::EventResponder(LLEventPumps::instance(),
-                                                       request,
-                                                       url, "POST", reply, error),
-                       LLSD(),      // headers
-                       (F32)timeout);
-    return false;
-}
-
-void LLSDMessage::EventResponder::httpSuccess()
-{
-    // If our caller passed an empty replyPump name, they're not
-    // listening: this is a fire-and-forget message. Don't bother posting
-    // to the pump whose name is "".
-    if (! mReplyPump.empty())
-    {
-        LLSD response(getContent());
-        mReqID.stamp(response);
-        mPumps.obtain(mReplyPump).post(response);
-    }
-    else                            // default success handling
-    {
-        LL_INFOS("LLSDMessage::EventResponder")
-            << "'" << mMessage << "' to '" << mTarget << "' succeeded"
-            << LL_ENDL;
-    }
-}
-
-void LLSDMessage::EventResponder::httpFailure()
-{
-    // If our caller passed an empty errorPump name, they're not
-    // listening: "default error handling is acceptable." Only post to an
-    // explicit pump name.
-    if (! mErrorPump.empty())
-    {
-        LLSD info(mReqID.makeResponse());
-        info["target"]  = mTarget;
-        info["message"] = mMessage;
-        info["status"]  = getStatus();
-        info["reason"]  = getReason();
-        info["content"] = getContent();
-        mPumps.obtain(mErrorPump).post(info);
-    }
-    else                        // default error handling
-    {
-        // convention seems to be to use LL_INFOS(), but that seems a bit casual?
-        LL_WARNS("LLSDMessage::EventResponder")
-            << "'" << mMessage << "' to '" << mTarget
-            << "' failed " << dumpResponse() << LL_ENDL;
-    }
-}
-
-LLSDMessage::ResponderAdapter::ResponderAdapter(LLHTTPClient::ResponderPtr responder,
-                                                const std::string& name):
-    mResponder(responder),
-    mReplyPump(name + ".reply", true), // tweak name for uniqueness
-    mErrorPump(name + ".error", true)
-{
-    mReplyPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, true));
-    mErrorPump.listen("self", boost::bind(&ResponderAdapter::listener, this, _1, false));
-}
-
-bool LLSDMessage::ResponderAdapter::listener(const LLSD& payload, bool success)
-{
-    if (success)
-    {
-        mResponder->successResult(payload);
-    }
-    else
-    {
-        mResponder->failureResult(payload["status"].asInteger(), payload["reason"], payload["content"]);
-    }
-
-    /*---------------- MUST BE LAST STATEMENT BEFORE RETURN ----------------*/
-    delete this;
-    // Destruction of mResponder will usually implicitly free its referent as well
-    /*------------------------- NOTHING AFTER THIS -------------------------*/
-    return false;
-}
-
-void LLSDMessage::link()
-{
-}
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
deleted file mode 100755
index e5d532d6a42c100823a36bd36d617e9e01f894f0..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdmessage.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file   llsdmessage.h
- * @author Nat Goodspeed
- * @date   2008-10-30
- * @brief  API intended to unify sending capability, UDP and TCP messages:
- *         https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
- * 
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLSDMESSAGE_H)
-#define LL_LLSDMESSAGE_H
-
-#include "llerror.h"                // LOG_CLASS()
-#include "llevents.h"               // LLEventPumps
-#include "llhttpclient.h"
-#include <string>
-#include <stdexcept>
-
-class LLSD;
-
-/**
- * Class managing the messaging API described in
- * https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes
- */
-class LLSDMessage
-{
-    LOG_CLASS(LLSDMessage);
-
-public:
-    LLSDMessage();
-
-    /// Exception if you specify arguments badly
-    struct ArgError: public std::runtime_error
-    {
-        ArgError(const std::string& what):
-            std::runtime_error(std::string("ArgError: ") + what) {}
-    };
-
-    /**
-     * The response idiom used by LLSDMessage -- LLEventPump names on which to
-     * post reply or error -- is designed for the case in which your
-     * reply/error handlers are methods on the same class as the method
-     * sending the message. Any state available to the sending method that
-     * must be visible to the reply/error methods can conveniently be stored
-     * on that class itself, if it's not already.
-     *
-     * The LLHTTPClient::Responder idiom requires a separate instance of a
-     * separate class so that it can dispatch to the code of interest by
-     * calling canonical virtual methods. Interesting state must be copied
-     * into that new object. 
-     *
-     * With some trepidation, because existing response code is packaged in
-     * LLHTTPClient::Responder subclasses, we provide this adapter class
-     * <i>for transitional purposes only.</i> Instantiate a new heap
-     * ResponderAdapter with your new LLHTTPClient::ResponderPtr. Pass
-     * ResponderAdapter::getReplyName() and/or getErrorName() in your
-     * LLSDMessage (or LLViewerRegion::getCapAPI()) request event. The
-     * ResponderAdapter will call the appropriate Responder method, then
-     * @c delete itself.
-     */
-    class ResponderAdapter
-    {
-    public:
-        /**
-         * Bind the new LLHTTPClient::Responder subclass instance.
-         *
-         * Passing the constructor a name other than the default is only
-         * interesting if you suspect some usage will lead to an exception or
-         * log message.
-         */
-        ResponderAdapter(LLHTTPClient::ResponderPtr responder,
-                         const std::string& name="ResponderAdapter");
-
-        /// EventPump name on which LLSDMessage should post reply event
-        std::string getReplyName() const { return mReplyPump.getName(); }
-        /// EventPump name on which LLSDMessage should post error event
-        std::string getErrorName() const { return mErrorPump.getName(); }
-
-    private:
-        // We have two different LLEventStreams, though we route them both to
-        // the same listener, so that we can bind an extra flag identifying
-        // which case (reply or error) reached that listener.
-        bool listener(const LLSD&, bool success);
-
-        LLHTTPClient::ResponderPtr mResponder;
-        LLEventStream mReplyPump, mErrorPump;
-    };
-
-    /**
-     * Force our implementation file to be linked with caller. The .cpp file
-     * contains a static instance of this class, which must be linked into the
-     * executable to support the canonical listener. But since the primary
-     * interface to that static instance is via a named LLEventPump rather
-     * than by direct reference, the linker doesn't necessarily perceive the
-     * necessity to bring in the translation unit. Referencing this dummy
-     * method forces the issue.
-     */
-    static void link();
-
-private:
-    friend class LLCapabilityListener;
-    /// Responder used for internal purposes by LLSDMessage and
-    /// LLCapabilityListener. Others should use higher-level APIs.
-    class EventResponder: public LLHTTPClient::Responder
-    {
-        LOG_CLASS(EventResponder);
-    public:
-        /**
-         * LLHTTPClient::Responder that dispatches via named LLEventPump instances.
-         * We bind LLEventPumps, even though it's an LLSingleton, for testability.
-         * We bind the string names of the desired LLEventPump instances rather
-         * than actually obtain()ing them so we only obtain() the one we're going
-         * to use. If the caller doesn't bother to listen() on it, the other pump
-         * may never materialize at all.
-         * @a target and @a message are only to clarify error processing.
-         * For a capability message, @a target should be the region description,
-         * @a message should be the capability name.
-         * For a service with a visible URL, pass the URL as @a target and the HTTP verb
-         * (e.g. "POST") as @a message.
-         */
-        EventResponder(LLEventPumps& pumps,
-                       const LLSD& request,
-                       const std::string& target, const std::string& message,
-                       const std::string& replyPump, const std::string& errorPump):
-            mPumps(pumps),
-            mReqID(request),
-            mTarget(target),
-            mMessage(message),
-            mReplyPump(replyPump),
-            mErrorPump(errorPump)
-        {}
-    
-    protected:
-        virtual void httpSuccess();
-        virtual void httpFailure();
-    
-    private:
-        LLEventPumps& mPumps;
-        LLReqID mReqID;
-        const std::string mTarget, mMessage, mReplyPump, mErrorPump;
-    };
-
-private:
-    bool httpListener(const LLSD&);
-    LLEventStream mEventPump;
-};
-
-#endif /* ! defined(LL_LLSDMESSAGE_H) */
diff --git a/indra/llmessage/llsdrpcclient.cpp b/indra/llmessage/llsdrpcclient.cpp
deleted file mode 100755
index eb773ceb3afa64b9d9dc7fe092d16027818d8776..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdrpcclient.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-/** 
- * @file llsdrpcclient.cpp
- * @author Phoenix
- * @date 2005-11-05
- * @brief Implementation of the llsd client classes.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llsdrpcclient.h"
-
-#include "llbufferstream.h"
-#include "llfasttimer.h"
-#include "llfiltersd2xmlrpc.h"
-#include "llpumpio.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "llurlrequest.h"
-
-/**
- * String constants
- */
-static std::string LLSDRPC_RESPONSE_NAME("response");
-static std::string LLSDRPC_FAULT_NAME("fault");
-
-/** 
- * LLSDRPCResponse
- */
-LLSDRPCResponse::LLSDRPCResponse() :
-	mIsError(false),
-	mIsFault(false)
-{
-}
-
-// virtual
-LLSDRPCResponse::~LLSDRPCResponse()
-{
-}
-
-bool LLSDRPCResponse::extractResponse(const LLSD& sd)
-{
-	bool rv = true;
-	if(sd.has(LLSDRPC_RESPONSE_NAME))
-	{
-		mReturnValue = sd[LLSDRPC_RESPONSE_NAME];
-		mIsFault = false;
-	}
-	else if(sd.has(LLSDRPC_FAULT_NAME))
-	{
-		mReturnValue = sd[LLSDRPC_FAULT_NAME];
-		mIsFault = true;
-	}
-	else
-	{
-		mReturnValue.clear();
-		mIsError = true;
-		rv = false;
-	}
-	return rv;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_SDRPC_RESPONSE("SDRPC Response");
-
-// virtual
-LLIOPipe::EStatus LLSDRPCResponse::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_SDRPC_RESPONSE);
-	PUMP_DEBUG;
-	if(mIsError)
-	{
-		error(pump);
-	}
-	else if(mIsFault)
-	{
-		fault(pump);
-	}
-	else
-	{
-		response(pump);
-	}
-	PUMP_DEBUG;
-	return STATUS_DONE;
-}
-
-/** 
- * LLSDRPCClient
- */
-
-LLSDRPCClient::LLSDRPCClient() :
-	mState(STATE_NONE),
-	mQueue(EPBQ_PROCESS)
-{
-}
-
-// virtual
-LLSDRPCClient::~LLSDRPCClient()
-{
-}
-
-bool LLSDRPCClient::call(
-	const std::string& uri,
-	const std::string& method,
-	const LLSD& parameter,
-	LLSDRPCResponse* response,
-	EPassBackQueue queue)
-{
-	//LL_INFOS() << "RPC: " << uri << "." << method << "(" << *parameter << ")"
-	//		<< LL_ENDL;
-	if(method.empty() || !response)
-	{
-		return false;
-	}
-	mState = STATE_READY;
-	mURI.assign(uri);
-	std::stringstream req;
-	req << LLSDRPC_REQUEST_HEADER_1 << method
-		<< LLSDRPC_REQUEST_HEADER_2;
-	LLSDSerialize::toNotation(parameter, req);
-	req << LLSDRPC_REQUEST_FOOTER;
-	mRequest = req.str();
-	mQueue = queue;
-	mResponse = response;
-	return true;
-}
-
-bool LLSDRPCClient::call(
-	const std::string& uri,
-	const std::string& method,
-	const std::string& parameter,
-	LLSDRPCResponse* response,
-	EPassBackQueue queue)
-{
-	//LL_INFOS() << "RPC: " << uri << "." << method << "(" << parameter << ")"
-	//		<< LL_ENDL;
-	if(method.empty() || parameter.empty() || !response)
-	{
-		return false;
-	}
-	mState = STATE_READY;
-	mURI.assign(uri);
-	std::stringstream req;
-	req << LLSDRPC_REQUEST_HEADER_1 << method
-		<< LLSDRPC_REQUEST_HEADER_2 << parameter
-		<< LLSDRPC_REQUEST_FOOTER;
-	mRequest = req.str();
-	mQueue = queue;
-	mResponse = response;
-	return true;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_SDRPC_CLIENT("SDRPC Client");
-
-// virtual
-LLIOPipe::EStatus LLSDRPCClient::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_PROCESS_SDRPC_CLIENT);
-	PUMP_DEBUG;
-	if((STATE_NONE == mState) || (!pump))
-	{
-		// You should have called the call() method already.
-		return STATUS_PRECONDITION_NOT_MET;
-	}
-	EStatus rv = STATUS_DONE;
-	switch(mState)
-	{
-	case STATE_READY:
-	{
-		PUMP_DEBUG;
-//		LL_DEBUGS() << "LLSDRPCClient::process_impl STATE_READY" << LL_ENDL;
-		buffer->append(
-			channels.out(),
-			(U8*)mRequest.c_str(),
-			mRequest.length());
-		context[CONTEXT_DEST_URI_SD_LABEL] = mURI;
-		mState = STATE_WAITING_FOR_RESPONSE;
-		break;
-	}
-	case STATE_WAITING_FOR_RESPONSE:
-	{
-		PUMP_DEBUG;
-		// The input channel has the sd response in it.
-		//LL_DEBUGS() << "LLSDRPCClient::process_impl STATE_WAITING_FOR_RESPONSE"
-		//		 << LL_ENDL;
-		LLBufferStream resp(channels, buffer.get());
-		LLSD sd;
-		LLSDSerialize::fromNotation(sd, resp, buffer->count(channels.in()));
-		LLSDRPCResponse* response = (LLSDRPCResponse*)mResponse.get();
-		if (!response)
-		{
-			mState = STATE_DONE;
-			break;
-		}
-		response->extractResponse(sd);
-		if(EPBQ_PROCESS == mQueue)
-		{
-			LLPumpIO::chain_t chain;
-			chain.push_back(mResponse);
-			pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
-		}
-		else
-		{
-			pump->respond(mResponse.get());
-		}
-		mState = STATE_DONE;
-		break;
-	}
-	case STATE_DONE:
-	default:
-		PUMP_DEBUG;
-		LL_INFOS() << "invalid state to process" << LL_ENDL;
-		rv = STATUS_ERROR;
-		break;
-	}
-	return rv;
-}
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h
deleted file mode 100755
index c4e0333ca3250f6ca733a24c7cb0b5ed561b6bdf..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdrpcclient.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/** 
- * @file llsdrpcclient.h
- * @author Phoenix
- * @date 2005-11-05
- * @brief Implementation and helpers for structure data RPC clients.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSDRPCCLIENT_H
-#define LL_LLSDRPCCLIENT_H
-
-/** 
- * This file declares classes to encapsulate a basic structured data
- * remote procedure client.
- */
-
-#include "llchainio.h"
-#include "llfiltersd2xmlrpc.h"
-#include "lliopipe.h"
-#include "llurlrequest.h"
-
-/** 
- * @class LLSDRPCClientResponse
- * @brief Abstract base class to represent a response from an SD server.
- *
- * This is used as a base class for callbacks generated from an
- * structured data remote procedure call. The
- * <code>extractResponse</code> method will deal with the llsdrpc method
- * call overhead, and keep track of what to call during the next call
- * into <code>process</code>. If you use this as a base class, you
- * need to implement <code>response</code>, <code>fault</code>, and
- * <code>error</code> to do something useful. When in those methods,
- * you can parse and utilize the mReturnValue member data.
- */
-class LLSDRPCResponse : public LLIOPipe
-{
-public:
-	LLSDRPCResponse();
-	virtual ~LLSDRPCResponse();
-
-	/** 
-	 * @brief This method extracts the response out of the sd passed in
-	 *
-	 * Any appropriate data found in the sd passed in will be
-	 * extracted and managed by this object - not copied or cloned. It
-	 * will still be up to the caller to delete the pointer passed in.
-	 * @param sd The raw structured data response from the remote server.
-	 * @return Returns true if this was able to parse the structured data.
-	 */
-	bool extractResponse(const LLSD& sd);
-
-protected:
-	/** 
-	 * @brief Method called when the response is ready.
-	 */
-	virtual bool response(LLPumpIO* pump) = 0;
-
-	/** 
-	 * @brief Method called when a fault is generated by the remote server.
-	 */
-	virtual bool fault(LLPumpIO* pump) = 0;
-
-	/** 
-	 * @brief Method called when there was an error
-	 */
-	virtual bool error(LLPumpIO* pump) = 0;
-
-protected:
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-	
-protected:
-	LLSD mReturnValue;
-	bool mIsError;
-	bool mIsFault;
-};
-
-/** 
- * @class LLSDRPCClient
- * @brief Client class for a structured data remote procedure call.
- *
- * This class helps deal with making structured data calls to a remote
- * server. You can visualize the calls as:
- * <code>
- * response = uri.method(parameter)
- * </code>
- * where you pass in everything to <code>call</code> and this class
- * takes care of the rest of the details.
- * In typical usage, you will derive a class from this class and
- * provide an API more useful for the specific application at
- * hand. For example, if you were writing a service to send an instant
- * message, you could create an API for it to send the messsage, and
- * that class would do the work of translating it into the method and
- * parameter, find the destination, and invoke <code>call</call> with
- * a useful implementation of LLSDRPCResponse passed in to handle the
- * response from the network.
- */
-class LLSDRPCClient : public LLIOPipe
-{
-public:
-	LLSDRPCClient();
-	virtual ~LLSDRPCClient();
-
-	/** 
-	 * @brief Enumeration for tracking which queue to process the
-	 * response.
-	 */
-	enum EPassBackQueue
-	{
-		EPBQ_PROCESS,
-		EPBQ_CALLBACK,
-	};
-
-	/** 
-	 * @brief Call a method on a remote LLSDRPCServer
-	 *
-	 * @param uri The remote object to call, eg,
-	 * http://localhost/usher. If you are using a factory with a fixed
-	 * url, the uri passed in will probably be ignored.
-	 * @param method The method to call on the remote object
-	 * @param parameter The parameter to pass into the remote
-	 * object. It is up to the caller to delete the value passed in.
-	 * @param response The object which gets the response.
-	 * @param queue Specifies to call the response on the process or
-	 * callback queue.
-	 * @return Returns true if this object will be able to make the RPC call.
-	 */
-	bool call(
-		const std::string& uri,
-		const std::string& method,
-		const LLSD& parameter,
-		LLSDRPCResponse* response,
-		EPassBackQueue queue);
-
-	/** 
-	 * @brief Call a method on a remote LLSDRPCServer
-	 *
-	 * @param uri The remote object to call, eg,
-	 * http://localhost/usher. If you are using a factory with a fixed
-	 * url, the uri passed in will probably be ignored.
-	 * @param method The method to call on the remote object
-	 * @param parameter The seriailized parameter to pass into the
-	 * remote object.
-	 * @param response The object which gets the response.
-	 * @param queue Specifies to call the response on the process or
-	 * callback queue.
-	 * @return Returns true if this object will be able to make the RPC call.
-	 */
-	bool call(
-		const std::string& uri,
-		const std::string& method,
-		const std::string& parameter,
-		LLSDRPCResponse* response,
-		EPassBackQueue queue);
-
-protected:
-	/** 
-	 * @brief Enumeration for tracking client state.
-	 */
-	enum EState
-	{
-		STATE_NONE,
-		STATE_READY,
-		STATE_WAITING_FOR_RESPONSE,
-		STATE_DONE
-	};
-	
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-
-protected:
-	EState mState;
-	std::string mURI;
-	std::string mRequest;
-	EPassBackQueue mQueue;
-	LLIOPipe::ptr_t mResponse;
-};
-
-/** 
- * @class LLSDRPCClientFactory
- * @brief Basic implementation for making an SD RPC client factory
- *
- * This class eases construction of a basic sd rpc client. Here is an
- * example of it's use:
- * <code>
- *  class LLUsefulService : public LLService { ... }
- *  LLService::registerCreator(
- *    "useful",
- *    LLService::creator_t(new LLSDRPCClientFactory<LLUsefulService>))
- * </code>
- */
-template<class Client>
-class LLSDRPCClientFactory : public LLChainIOFactory
-{
-public:
-	LLSDRPCClientFactory() {}
-	LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
-	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
-	{
-		LL_DEBUGS() << "LLSDRPCClientFactory::build" << LL_ENDL;
-		LLURLRequest* http(new LLURLRequest(HTTP_POST));
-		if(!http->isValid())
-		{
-			LL_WARNS() << "Creating LLURLRequest failed." << LL_ENDL ;
-			delete http;
-			return false;
-		}
-
-		LLIOPipe::ptr_t service(new Client);
-		chain.push_back(service);		
-		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_LLSD);
-		if(mURL.empty())
-		{
-			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
-		}
-		else
-		{
-			http->setURL(mURL);
-		}
-		chain.push_back(http_pipe);
-		chain.push_back(service);
-		return true;
-	}
-protected:
-	std::string mURL;
-};
-
-/** 
- * @class LLXMLSDRPCClientFactory
- * @brief Basic implementation for making an XMLRPC to SD RPC client factory
- *
- * This class eases construction of a basic sd rpc client which uses
- * xmlrpc as a serialization grammar. Here is an example of it's use:
- * <code>
- *  class LLUsefulService : public LLService { ... }
- *  LLService::registerCreator(
- *    "useful",
- *    LLService::creator_t(new LLXMLSDRPCClientFactory<LLUsefulService>))
- * </code>
- */
-template<class Client>
-class LLXMLSDRPCClientFactory : public LLChainIOFactory
-{
-public:
-	LLXMLSDRPCClientFactory() {}
-	LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
-	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
-	{
-		LL_DEBUGS() << "LLXMLSDRPCClientFactory::build" << LL_ENDL;
-
-		LLURLRequest* http(new LLURLRequest(HTTP_POST));
-		if(!http->isValid())
-		{
-			LL_WARNS() << "Creating LLURLRequest failed." << LL_ENDL ;
-			delete http;
-			return false ;
-		}
-		LLIOPipe::ptr_t service(new Client);
-		chain.push_back(service);		
-		LLIOPipe::ptr_t http_pipe(http);
-		http->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
-		if(mURL.empty())
-		{
-			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
-		}
-		else
-		{
-			http->setURL(mURL);
-		}
-		chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest(NULL)));
-		chain.push_back(http_pipe);
-		chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
-		chain.push_back(service);
-		return true;
-	}
-protected:
-	std::string mURL;
-};
-
-#endif // LL_LLSDRPCCLIENT_H
diff --git a/indra/llmessage/llsdrpcserver.cpp b/indra/llmessage/llsdrpcserver.cpp
deleted file mode 100755
index c3ed19889e83e5084f10296b1f9560a689b790e8..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdrpcserver.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-/** 
- * @file llsdrpcserver.cpp
- * @author Phoenix
- * @date 2005-10-11
- * @brief Implementation of the LLSDRPCServer and related classes.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llsdrpcserver.h"
-
-#include "llbuffer.h"
-#include "llbufferstream.h"
-#include "llfasttimer.h"
-#include "llpumpio.h"
-#include "llsdserialize.h"
-#include "llstl.h"
-
-static const char FAULT_PART_1[] = "{'fault':{'code':i";
-static const char FAULT_PART_2[] = ", 'description':'";
-static const char FAULT_PART_3[] = "'}}";
-
-static const char RESPONSE_PART_1[] = "{'response':";
-static const char RESPONSE_PART_2[] = "}";
-
-static const S32 FAULT_GENERIC = 1000;
-static const S32 FAULT_METHOD_NOT_FOUND = 1001;
-
-static const std::string LLSDRPC_METHOD_SD_NAME("method");
-static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
-
-
-/**
- * LLSDRPCServer
- */
-LLSDRPCServer::LLSDRPCServer() :
-	mState(LLSDRPCServer::STATE_NONE),
-	mPump(NULL),
-	mLock(0)
-{
-}
-
-LLSDRPCServer::~LLSDRPCServer()
-{
-	std::for_each(
-		mMethods.begin(),
-		mMethods.end(),
-		llcompose1(
-			DeletePointerFunctor<LLSDRPCMethodCallBase>(),
-			llselect2nd<method_map_t::value_type>()));
-	std::for_each(
-		mCallbackMethods.begin(),
-		mCallbackMethods.end(),
-		llcompose1(
-			DeletePointerFunctor<LLSDRPCMethodCallBase>(),
-			llselect2nd<method_map_t::value_type>()));
-}
-
-
-// virtual
-ESDRPCSStatus LLSDRPCServer::deferredResponse(
-        const LLChannelDescriptors& channels,
-	LLBufferArray* data) {
-    // subclass should provide a sane implementation
-    return ESDRPCS_DONE;
-}
-
-void LLSDRPCServer::clearLock()
-{
-	if(mLock && mPump)
-	{
-		mPump->clearLock(mLock);
-		mPump = NULL;
-		mLock = 0;
-	}
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_SDRPC_SERVER("SDRPC Server");
-
-// virtual
-LLIOPipe::EStatus LLSDRPCServer::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_PROCESS_SDRPC_SERVER);
-	PUMP_DEBUG;
-//	LL_DEBUGS() << "LLSDRPCServer::process_impl" << LL_ENDL;
-	// Once we have all the data, We need to read the sd on
-	// the the in channel, and respond on  the out channel
-	if(!eos) return STATUS_BREAK;
-	if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
-
-	std::string method_name;
-	LLIOPipe::EStatus status = STATUS_DONE;
-
-	switch(mState)
-	{
-	case STATE_DEFERRED:
-		PUMP_DEBUG;
-		if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
-		{
-			buildFault(
-				channels,
-				buffer.get(),
-				FAULT_GENERIC,
-				"deferred response failed.");
-		}
-		mState = STATE_DONE;
-		return STATUS_DONE;
-
-	case STATE_DONE:
-//		LL_DEBUGS() << "STATE_DONE" << LL_ENDL;
-		break;
-	case STATE_CALLBACK:
-//		LL_DEBUGS() << "STATE_CALLBACK" << LL_ENDL;
-		PUMP_DEBUG;
-		method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
-		if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
-		{
-			if(ESDRPCS_DONE != callbackMethod(
-				   method_name,
-				   mRequest[LLSDRPC_PARAMETER_SD_NAME],
-				   channels,
-				   buffer.get()))
-			{
-				buildFault(
-					channels,
-					buffer.get(),
-					FAULT_GENERIC,
-					"Callback method call failed.");
-			}
-		}
-		else
-		{
-			// this should never happen, since we should not be in
-			// this state unless we originally found a method and
-			// params during the first call to process.
-			buildFault(
-				channels,
-				buffer.get(),
-				FAULT_GENERIC,
-				"Invalid LLSDRPC sever state - callback without method.");
-		}
-		pump->clearLock(mLock);
-		mLock = 0;
-		mState = STATE_DONE;
-		break;
-	case STATE_NONE:
-//		LL_DEBUGS() << "STATE_NONE" << LL_ENDL;
-	default:
-	{
-		// First time we got here - process the SD request, and call
-		// the method.
-		PUMP_DEBUG;
-		LLBufferStream istr(channels, buffer.get());
-		mRequest.clear();
-		LLSDSerialize::fromNotation(
-			mRequest,
-			istr,
-			buffer->count(channels.in()));
-
-		// { 'method':'...', 'parameter': ... }
-		method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
-		if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
-		{
-			ESDRPCSStatus rv = callMethod(
-				method_name,
-				mRequest[LLSDRPC_PARAMETER_SD_NAME],
-				channels,
-				buffer.get());
-			switch(rv)
-			{
-			case ESDRPCS_DEFERRED:
-				mPump = pump;
-				mLock = pump->setLock();
-				mState = STATE_DEFERRED;
-				status = STATUS_BREAK;
-				break;
-
-			case ESDRPCS_CALLBACK:
-			{
-				mState = STATE_CALLBACK;
-				LLPumpIO::LLLinkInfo link;
-				link.mPipe = LLIOPipe::ptr_t(this);
-				link.mChannels = channels;
-				LLPumpIO::links_t links;
-				links.push_back(link);
-				pump->respond(links, buffer, context);
-				mLock = pump->setLock();
-				status = STATUS_BREAK;
-				break;
-			}
-			case ESDRPCS_DONE:
-				mState = STATE_DONE;
-				break;
-			case ESDRPCS_ERROR:
-			default:
-				buildFault(
-					channels,
-					buffer.get(),
-					FAULT_GENERIC,
-					"Method call failed.");
-				break;
-			}
-		}
-		else
-		{
-			// send a fault
-			buildFault(
-				channels,
-				buffer.get(),
-				FAULT_GENERIC,
-				"Unable to find method and parameter in request.");
-		}
-		break;
-	}
-	}
-
-	PUMP_DEBUG;
-	return status;
-}
-
-// virtual
-ESDRPCSStatus LLSDRPCServer::callMethod(
-	const std::string& method,
-	const LLSD& params,
-	const LLChannelDescriptors& channels,
-	LLBufferArray* response)
-{
-	// Try to find the method in the method table.
-	ESDRPCSStatus rv = ESDRPCS_DONE;
-	method_map_t::iterator it = mMethods.find(method);
-	if(it != mMethods.end())
-	{
-		rv = (*it).second->call(params, channels, response);
-	}
-	else
-	{
-		it = mCallbackMethods.find(method);
-		if(it == mCallbackMethods.end())
-		{
-			// method not found.
-			std::ostringstream message;
-			message << "rpc server unable to find method: " << method;
-			buildFault(
-				channels,
-				response,
-				FAULT_METHOD_NOT_FOUND,
-				message.str());
-		}
-		else
-		{
-			// we found it in the callback methods - tell the process
-			// to coordinate calling on the pump callback.
-			return ESDRPCS_CALLBACK;
-		}
-	}
-	return rv;
-}
-
-// virtual
-ESDRPCSStatus LLSDRPCServer::callbackMethod(
-	const std::string& method,
-	const LLSD& params,
-	const LLChannelDescriptors& channels,
-	LLBufferArray* response)
-{
-	// Try to find the method in the callback method table.
-	ESDRPCSStatus rv = ESDRPCS_DONE;
-	method_map_t::iterator it = mCallbackMethods.find(method);
-	if(it != mCallbackMethods.end())
-	{
-		rv = (*it).second->call(params, channels, response);
-	}
-	else
-	{
-		std::ostringstream message;
-		message << "pcserver unable to find callback method: " << method;
-		buildFault(
-			channels,
-			response,
-			FAULT_METHOD_NOT_FOUND,
-			message.str());
-	}
-	return rv;
-}
-
-// static
-void LLSDRPCServer::buildFault(
-	const LLChannelDescriptors& channels,
-	LLBufferArray* data,
-	S32 code,
-	const std::string& msg)
-{
-	LLBufferStream ostr(channels, data);
-	ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
-	LL_INFOS() << "LLSDRPCServer::buildFault: " << code << ", " << msg << LL_ENDL;
-}
-
-// static
-void LLSDRPCServer::buildResponse(
-	const LLChannelDescriptors& channels,
-	LLBufferArray* data,
-	const LLSD& response)
-{
-	LLBufferStream ostr(channels, data);
-	ostr << RESPONSE_PART_1;
-	LLSDSerialize::toNotation(response, ostr);
-	ostr << RESPONSE_PART_2;
-#if LL_DEBUG
-	std::ostringstream debug_ostr;
-	debug_ostr << "LLSDRPCServer::buildResponse: ";
-	LLSDSerialize::toNotation(response, debug_ostr);
-	LL_INFOS() << debug_ostr.str() << LL_ENDL;
-#endif
-}
diff --git a/indra/llmessage/llsdrpcserver.h b/indra/llmessage/llsdrpcserver.h
deleted file mode 100755
index 415bd31c26e11f0412cc5565a11c6731c6c84a9a..0000000000000000000000000000000000000000
--- a/indra/llmessage/llsdrpcserver.h
+++ /dev/null
@@ -1,360 +0,0 @@
-/** 
- * @file llsdrpcserver.h
- * @author Phoenix
- * @date 2005-10-11
- * @brief Declaration of the structured data remote procedure call server.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSDRPCSERVER_H
-#define LL_LLSDRPCSERVER_H
-
-/** 
- * I've set this up to be pretty easy to use when you want to make a
- * structured data rpc server which responds to methods by
- * name. Derive a class from the LLSDRPCServer, and during
- * construction (or initialization if you have the luxury) map method
- * names to pointers to member functions. This will look a lot like:
- *
- * <code>
- *  class LLMessageAgents : public LLSDRPCServer {<br>
- *  public:<br>
- *    typedef LLSDRPCServer<LLUsher> mem_fn_t;<br>
- *    LLMessageAgents() {<br>
- *      mMethods["message"] = new mem_fn_t(this, &LLMessageAgents::rpc_IM);<br>
- *      mMethods["alert"] = new mem_fn_t(this, &LLMessageAgents::rpc_Alrt);<br>
- *    }<br>
- *  protected:<br>
- *    rpc_IM(const LLSD& params,
- *		const LLChannelDescriptors& channels,
- *		LLBufferArray* data)
- *		{...}<br>
- *    rpc_Alert(const LLSD& params,
- *		const LLChannelDescriptors& channels,
- *		LLBufferArray* data)
- *		{...}<br>
- *  };<br>
- * </code>
- *
- * The params are an array where each element in the array is a single
- * parameter in the call.
- *
- * It is up to you to pack a valid serialized llsd response into the
- * data object passed into the method, but you can use the helper
- * methods below to help.
- */
-
-#include <map>
-#include "lliopipe.h"
-#include "lliohttpserver.h"
-#include "llfiltersd2xmlrpc.h"
-
-class LLSD;
-
-/** 
- * @brief Enumeration for specifying server method call status. This
- * enumeration controls how the server class will manage the pump
- * process/callback mechanism.
- */
-enum ESDRPCSStatus
-{
- 	// The call went ok, but the response is not yet ready. The
- 	// method will arrange for the clearLock() call to be made at
- 	// a later date, after which, once the chain is being pumped
-	// again, deferredResponse() will be called to gather the result
- 	ESDRPCS_DEFERRED,
-
-	// The LLSDRPCServer would like to handle the method on the
-	// callback queue of the pump.
-	ESDRPCS_CALLBACK,
-
-	// The method call finished and generated output.
-	ESDRPCS_DONE,
-
-	// Method failed for some unspecified reason - you should avoid
-	// this. A generic fault will be sent to the output.
-	ESDRPCS_ERROR,
-
-	ESDRPCS_COUNT,
-};
-
-/** 
- * @class LLSDRPCMethodCallBase
- * @brief Base class for calling a member function in an sd rpcserver
- * implementation.
- */
-class LLSDRPCMethodCallBase
-{
-public:
-	LLSDRPCMethodCallBase() {}
-	virtual ~LLSDRPCMethodCallBase() {}
-
-	virtual ESDRPCSStatus call(
-		const LLSD& params,
-		const LLChannelDescriptors& channels,
-		LLBufferArray* response) = 0;
-protected:
-};
-
-/** 
- * @class LLSDRPCMethodCall
- * @brief Class which implements member function calls.
- */
-template<class Server>
-class LLSDRPCMethodCall : public LLSDRPCMethodCallBase
-{
-public:
-	typedef ESDRPCSStatus (Server::*mem_fn)(
-		const LLSD& params,
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data);
-	LLSDRPCMethodCall(Server* s, mem_fn fn) :
-		mServer(s),
-		mMemFn(fn)
-	{
-	}
-	virtual ~LLSDRPCMethodCall() {}
-	virtual ESDRPCSStatus call(
-		const LLSD& params,
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data)
-	{
-		return (*mServer.*mMemFn)(params, channels, data);
-	}
-
-protected:
-	Server* mServer;
-	mem_fn mMemFn;
-	//bool (Server::*mMemFn)(const LLSD& params, LLBufferArray& data);
-};
-
-
-/** 
- * @class LLSDRPCServer
- * @brief Basic implementation of a structure data rpc server
- *
- * The rpc server is also designed to appropriately straddle the pump
- * <code>process()</code> and <code>callback()</code> to specify which
- * thread you want to work on when handling a method call. The
- * <code>mMethods</code> methods are called from
- * <code>process()</code>, while the <code>mCallbackMethods</code> are
- * called when a pump is in a <code>callback()</code> cycle.
- */
-class LLSDRPCServer : public LLIOPipe
-{
-public:
-	LLSDRPCServer();
-	virtual ~LLSDRPCServer();
-
-	/**
-	 * enumeration for generic fault codes
-	 */
-	enum
-	{
-		FAULT_BAD_REQUEST = 2000,
-		FAULT_NO_RESPONSE = 2001,
-	};
-
-	/** 
-	 * @brief Call this method to return an rpc fault.
-	 *
-	 * @param channel The channel for output on the data buffer
-	 * @param data buffer which will recieve the final output 
-	 * @param code The fault code 
-	 * @param msg The fault message 
-	 */
-	static void buildFault(
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data,
-		S32 code,
-		const std::string& msg);
-
-	/** 
-	 * @brief Call this method to build an rpc response.
-	 *
-	 * @param channel The channel for output on the data buffer
-	 * @param data buffer which will recieve the final output 
-	 * @param response The return value from the method call
-	 */
-	static void buildResponse(
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data,
-		const LLSD& response);
-
-protected:
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-
-protected:
-
-	/** 
-	 * @brief Enumeration to track the state of the rpc server instance
-	 */
-	enum EState
-	{
-		STATE_NONE,
-		STATE_CALLBACK,
-		STATE_DEFERRED,
-		STATE_DONE
-	};
-
-	/** 
-	 * @brief This method is called when an http post comes in.
-	 *
-	 * The default behavior is to look at the method name, look up the
-	 * method in the method table, and call it. If the method is not
-	 * found, this function will build a fault response.  You can
-	 * implement your own version of this function if you want to hard
-	 * wire some behavior or optimize things a bit.
-	 * @param method The method name being called
-	 * @param params The parameters
-	 * @param channel The channel for output on the data buffer
-	 * @param data The http data
-	 * @return Returns the status of the method call, done/deferred/etc
-	 */
-	virtual ESDRPCSStatus callMethod(
-		const std::string& method,
-		const LLSD& params,
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data);
-
-	/** 
-	 * @brief This method is called when a pump callback is processed.
-	 *
-	 * The default behavior is to look at the method name, look up the
-	 * method in the callback method table, and call it. If the method
-	 * is not found, this function will build a fault response.  You
-	 * can implement your own version of this function if you want to
-	 * hard wire some behavior or optimize things a bit.
-	 * @param method The method name being called
-	 * @param params The parameters
-	 * @param channel The channel for output on the data buffer
-	 * @param data The http data
-	 * @return Returns the status of the method call, done/deferred/etc
-	 */
-	virtual ESDRPCSStatus callbackMethod(
-		const std::string& method,
-		const LLSD& params,
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data);
-
-	/**
-	 * @brief Called after a deferred service is unlocked
-	 *
-	 * If a method returns ESDRPCS_DEFERRED, then the service chain
-	 * will be locked and not processed until some other system calls
-	 * clearLock() on the service instance again.  At that point,
-	 * once the pump starts processing the chain again, this method
-	 * will be called so the service can output the final result
-	 * into the buffers.
-	 */
-	virtual ESDRPCSStatus deferredResponse(
-		const LLChannelDescriptors& channels,
-		LLBufferArray* data);
-
-	// donovan put this public here 7/27/06
-public:
-	/**
-	 * @brief unlock a service that as ESDRPCS_DEFERRED
-	 */
-	void clearLock();
-
-protected:
-	EState mState;
-	LLSD mRequest;
-	LLPumpIO* mPump;
-	S32 mLock;
-	typedef std::map<std::string, LLSDRPCMethodCallBase*> method_map_t;
-	method_map_t mMethods;
-	method_map_t mCallbackMethods;
-};
-
-/** 
- * @name Helper Templates for making LLHTTPNodes
- *
- * These templates help in creating nodes for handing a service from
- * either SDRPC or XMLRPC, given a single implementation of LLSDRPCServer.
- *
- * To use it:
- * \code
- *  class LLUsefulServer : public LLSDRPCServer { ... }
- *
- *  LLHTTPNode& root = LLCreateHTTPWireServer(...);
- *  root.addNode("llsdrpc/useful", new LLSDRPCNode<LLUsefulServer>);
- *  root.addNode("xmlrpc/useful", new LLXMLRPCNode<LLUsefulServer>);
- * \endcode
- */
-//@{
-
-template<class Server>
-class LLSDRPCServerFactory : public LLChainIOFactory
-{
-public:
-	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
-	{
-		LL_DEBUGS() << "LLXMLSDRPCServerFactory::build" << LL_ENDL;
-		chain.push_back(LLIOPipe::ptr_t(new Server));
-		return true;
-	}
-};
-
-template<class Server>
-class LLSDRPCNode : public LLHTTPNodeForFactory<
-								LLSDRPCServerFactory<Server> >
-{
-};
-
-template<class Server>
-class LLXMLRPCServerFactory : public LLChainIOFactory
-{
-public:
-	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
-	{
-		LL_DEBUGS() << "LLXMLSDRPCServerFactory::build" << LL_ENDL;
-		chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
-		chain.push_back(LLIOPipe::ptr_t(new Server));
-		chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
-		return true;
-	}
-};
-
-template<class Server>
-class LLXMLRPCNode : public LLHTTPNodeForFactory<
-					 			LLXMLRPCServerFactory<Server> >
-{
-};
-
-//@}
-
-#endif // LL_LLSDRPCSERVER_H
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index 5bd1112cfe85dd2010478f7a3ef5432a96e8a2b3..33944f7883096cef990c13d128ffa7f9e5f07f71 100755
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -30,6 +30,7 @@
 #include "llhost.h"
 #include "llmessageconfig.h"
 #include "message.h"
+#include "llhttpconstants.h"
 
 
 bool LLTrustedMessageService::validate(const std::string& name, LLSD& context)
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
deleted file mode 100755
index 1294379eca2ab77ce6e6ab41b0f7daf74a6ceab0..0000000000000000000000000000000000000000
--- a/indra/llmessage/llurlrequest.cpp
+++ /dev/null
@@ -1,783 +0,0 @@
-/** 
- * @file llurlrequest.cpp
- * @author Phoenix
- * @date 2005-04-28
- * @brief Implementation of the URLRequest class and related classes.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llurlrequest.h"
-
-#include <algorithm>
-#include <openssl/x509_vfy.h>
-#include <openssl/ssl.h>
-#include "llcurl.h"
-#include "llfasttimer.h"
-#include "llioutil.h"
-#include "llproxy.h"
-#include "llpumpio.h"
-#include "llsd.h"
-#include "llstring.h"
-#include "apr_env.h"
-#include "llapr.h"
-
-/**
- * String constants
- */
-const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
-const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
-
-// These are defined in llhttpnode.h/llhttpnode.cpp
-extern const std::string CONTEXT_REQUEST;
-extern const std::string CONTEXT_RESPONSE;
-
-static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
-
-/**
- * class LLURLRequestDetail
- */
-class LLURLRequestDetail
-{
-public:
-	LLURLRequestDetail();
-	~LLURLRequestDetail();
-	std::string mURL;
-	LLCurlEasyRequest* mCurlRequest;
-	LLIOPipe::buffer_ptr_t mResponseBuffer;
-	LLChannelDescriptors mChannels;
-	U8* mLastRead;
-	U32 mBodyLimit;
-	S32 mByteAccumulator;
-	bool mIsBodyLimitSet;
-	LLURLRequest::SSLCertVerifyCallback mSSLVerifyCallback;
-};
-
-LLURLRequestDetail::LLURLRequestDetail() :
-	mCurlRequest(NULL),
-	mLastRead(NULL),
-	mBodyLimit(0),
-	mByteAccumulator(0),
-	mIsBodyLimitSet(false),
-    mSSLVerifyCallback(NULL)
-{
-	mCurlRequest = new LLCurlEasyRequest();
-	
-	if(!mCurlRequest->isValid()) //failed.
-	{
-		delete mCurlRequest ;
-		mCurlRequest = NULL ;
-	}
-}
-
-LLURLRequestDetail::~LLURLRequestDetail()
-{
-	delete mCurlRequest;
-	mLastRead = NULL;
-}
-
-void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *param)
-{
-	mDetail->mSSLVerifyCallback = callback;
-	mDetail->mCurlRequest->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this);
-	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, true);
-	mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2);	
-}
-
-
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validation
-
-CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param)
-{	
-	LLURLRequest *req = (LLURLRequest *)param;
-	if(req == NULL || req->mDetail->mSSLVerifyCallback == NULL)
-	{
-		SSL_CTX_set_cert_verify_callback((SSL_CTX *)sslctx, NULL, NULL);
-		return CURLE_OK;
-	}
-	SSL_CTX * ctx = (SSL_CTX *) sslctx;
-	// disable any default verification for server certs
-	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
-	// set the verification callback.
-	SSL_CTX_set_cert_verify_callback(ctx, req->mDetail->mSSLVerifyCallback, (void *)req);
-	// the calls are void
-	return CURLE_OK;
-	
-}
-
-/**
- * class LLURLRequest
- */
-
-
-LLURLRequest::LLURLRequest(EHTTPMethod action, bool follow_redirects /* = true */) :
-	mAction(action),
-	mFollowRedirects(follow_redirects)
-{
-	initialize();
-}
-
-LLURLRequest::LLURLRequest(
-	EHTTPMethod action,
-	const std::string& url,
-	bool follow_redirects /* = true */) :
-	mAction(action),
-	mFollowRedirects(follow_redirects)
-{
-	initialize();
-	setURL(url);
-}
-
-LLURLRequest::~LLURLRequest()
-{
-	delete mDetail;
-	mDetail = NULL ;
-}
-
-void LLURLRequest::setURL(const std::string& url)
-{
-	mDetail->mURL = url;
-	if (url.empty())
-	{
-		LL_WARNS() << "empty URL specified" << LL_ENDL;
-	}
-}
-
-const std::string& LLURLRequest::getURL() const
-{
-	return mDetail->mURL;
-}
-
-void LLURLRequest::addHeader(const std::string& header, const std::string& value /* = "" */)
-{
-	mDetail->mCurlRequest->slist_append(header, value);
-}
-
-void LLURLRequest::addHeaderRaw(const char* header)
-{
-	mDetail->mCurlRequest->slist_append(header);
-}
-
-void LLURLRequest::setBodyLimit(U32 size)
-{
-	mDetail->mBodyLimit = size;
-	mDetail->mIsBodyLimitSet = true;
-}
-
-void LLURLRequest::setCallback(LLURLRequestComplete* callback)
-{
-	mCompletionCallback = callback;
-	mDetail->mCurlRequest->setHeaderCallback(&headerCallback, (void*)callback);
-}
-
-// Added to mitigate the effect of libcurl looking
-// for the ALL_PROXY and http_proxy env variables
-// and deciding to insert a Pragma: no-cache
-// header! The only usage of this method at the
-// time of this writing is in llhttpclient.cpp
-// in the request() method, where this method
-// is called with use_proxy = FALSE
-void LLURLRequest::useProxy(bool use_proxy)
-{
-    static char *env_proxy;
-
-    if (use_proxy && (env_proxy == NULL))
-    {
-        apr_status_t status;
-        LLAPRPool pool;
-		status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool());
-        if (status != APR_SUCCESS)
-        {
-			status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool());
-        }
-        if (status != APR_SUCCESS)
-        {
-           use_proxy = FALSE;
-        }
-    }
-
-
-    LL_DEBUGS() << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL;
-
-    if (env_proxy && use_proxy)
-    {
-		mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
-    }
-    else
-    {
-        mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, "");
-    }
-}
-
-void LLURLRequest::useProxy(const std::string &proxy)
-{
-    mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, proxy);
-}
-
-void LLURLRequest::allowCookies()
-{
-	mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");
-}
-
-//virtual 
-bool LLURLRequest::isValid() 
-{
-	return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); 
-}
-
-// virtual
-LLIOPipe::EStatus LLURLRequest::handleError(
-	LLIOPipe::EStatus status,
-	LLPumpIO* pump)
-{
-	if(!isValid())
-	{
-		return STATUS_EXPIRED ;
-	}
-
-	if(mCompletionCallback && pump)
-	{
-		LLURLRequestComplete* complete = NULL;
-		complete = (LLURLRequestComplete*)mCompletionCallback.get();
-		complete->httpStatus(
-			HTTP_INTERNAL_ERROR,
-			LLIOPipe::lookupStatusString(status));
-		complete->responseStatus(status);
-		pump->respond(complete);
-		mCompletionCallback = NULL;
-	}
-	return status;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_REQUEST("URL Request");
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result");
-static LLTrace::BlockTimerStatHandle FTM_URL_PERFORM("Perform");
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond");
-static LLTrace::BlockTimerStatHandle FTM_URL_ADJUST_TIMEOUT("Adjust Timeout");
-
-// virtual
-LLIOPipe::EStatus LLURLRequest::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_REQUEST);
-	PUMP_DEBUG;
-	//LL_INFOS() << "LLURLRequest::process_impl()" << LL_ENDL;
-	if (!buffer) return STATUS_ERROR;
-	
-	// we're still waiting or prcessing, check how many
-	// bytes we have accumulated.
-	const S32 MIN_ACCUMULATION = 100000;
-	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
-	{
-		LL_RECORD_BLOCK_TIME(FTM_URL_ADJUST_TIMEOUT);
-		 // This is a pretty sloppy calculation, but this
-		 // tries to make the gross assumption that if data
-		 // is coming in at 56kb/s, then this transfer will
-		 // probably succeed. So, if we're accumlated
-		 // 100,000 bytes (MIN_ACCUMULATION) then let's
-		 // give this client another 2s to complete.
-		 const F32 TIMEOUT_ADJUSTMENT = 2.0f;
-		 mDetail->mByteAccumulator = 0;
-		 pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
-		 LL_DEBUGS() << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << LL_ENDL;
-		 if (mState == STATE_INITIALIZED)
-		 {
-			  LL_INFOS() << "LLURLRequest adjustTimeoutSeconds called during upload" << LL_ENDL;
-		 }
-	}
-
-	switch(mState)
-	{
-	case STATE_INITIALIZED:
-	{
-		PUMP_DEBUG;
-		// We only need to wait for input if we are uploading
-		// something.
-		if(((HTTP_PUT == mAction) || (HTTP_POST == mAction)) && !eos)
-		{
-			// we're waiting to get all of the information
-			return STATUS_BREAK;
-		}
-
-		// *FIX: bit of a hack, but it should work. The configure and
-		// callback method expect this information to be ready.
-		mDetail->mResponseBuffer = buffer;
-		mDetail->mChannels = channels;
-		if(!configure())
-		{
-			return STATUS_ERROR;
-		}
-		mState = STATE_WAITING_FOR_RESPONSE;
-
-		// *FIX: Maybe we should just go to the next state now...
-		return STATUS_BREAK;
-	}
-	case STATE_WAITING_FOR_RESPONSE:
-	case STATE_PROCESSING_RESPONSE:
-	{
-		PUMP_DEBUG;
-		LLIOPipe::EStatus status = STATUS_BREAK;
-		{
-			LL_RECORD_BLOCK_TIME(FTM_URL_PERFORM);
-			if(!mDetail->mCurlRequest->wait())
-			{
-				return status ;
-			}
-		}
-
-		bool keep_looping = true;
-		while(keep_looping)
-		{
-			CURLcode result;
-
-			bool newmsg = false;
-			{
-				LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_REQUEST_GET_RESULT);
-				newmsg = mDetail->mCurlRequest->getResult(&result);
-			}
-		
-			if(!newmsg)
-			{
-				// keep processing
-				break;
-			}
-		
-
-			mState = STATE_HAVE_RESPONSE;
-			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
-			context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
-			LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
-			switch(result)
-			{
-				case CURLE_OK:
-				case CURLE_WRITE_ERROR:
-					// NB: The error indication means that we stopped the
-					// writing due the body limit being reached
-					if(mCompletionCallback && pump)
-					{
-						LLURLRequestComplete* complete = NULL;
-						complete = (LLURLRequestComplete*)
-							mCompletionCallback.get();
-						complete->responseStatus(
-								result == CURLE_OK
-									? STATUS_OK : STATUS_STOP);
-						LLPumpIO::links_t chain;
-						LLPumpIO::LLLinkInfo link;
-						link.mPipe = mCompletionCallback;
-						link.mChannels = LLBufferArray::makeChannelConsumer(
-							channels);
-						chain.push_back(link);
-						{
-							LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_PUMP_RESPOND);
-							pump->respond(chain, buffer, context);
-						}
-						mCompletionCallback = NULL;
-					}
-					break;
-				case CURLE_FAILED_INIT:
-				case CURLE_COULDNT_CONNECT:
-					status = STATUS_NO_CONNECTION;
-					keep_looping = false;
-					break;
-				default:			// CURLE_URL_MALFORMAT
-					LL_WARNS() << "URLRequest Error: " << result
-							<< ", "
-							<< LLCurl::strerror(result)
-							<< ", "
-							<< (mDetail->mURL.empty() ? "<EMPTY URL>" : mDetail->mURL)
-							<< LL_ENDL;
-					status = STATUS_ERROR;
-					keep_looping = false;
-					break;
-			}
-		}
-		return status;
-	}
-	case STATE_HAVE_RESPONSE:
-		PUMP_DEBUG;
-		// we already stuffed everything into channel in in the curl
-		// callback, so we are done.
-		eos = true;
-		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
-		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
-		LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
-		return STATUS_DONE;
-
-	default:
-		PUMP_DEBUG;
-		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
-		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
-		LL_DEBUGS() << this << "Setting context to " << context << LL_ENDL;
-		return STATUS_ERROR;
-	}
-}
-
-void LLURLRequest::initialize()
-{
-	mState = STATE_INITIALIZED;
-	mDetail = new LLURLRequestDetail;
-
-	if(!isValid())
-	{
-		return ;
-	}
-
-	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
-	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
-	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
-	mRequestTransferedBytes = 0;
-	mResponseTransferedBytes = 0;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_URL_REQUEST_CONFIGURE("URL Configure");
-bool LLURLRequest::configure()
-{
-	LL_RECORD_BLOCK_TIME(FTM_URL_REQUEST_CONFIGURE);
-	
-	bool rv = false;
-	S32 bytes = mDetail->mResponseBuffer->countAfter(
-   		mDetail->mChannels.in(),
-		NULL);
-	switch(mAction)
-	{
-	case HTTP_HEAD:
-		mDetail->mCurlRequest->setopt(CURLOPT_HEADER, 1);
-		mDetail->mCurlRequest->setopt(CURLOPT_NOBODY, 1);
-		if (mFollowRedirects)
-		{
-			mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
-		}
-		rv = true;
-		break;
-	case HTTP_GET:
-		mDetail->mCurlRequest->setopt(CURLOPT_HTTPGET, 1);
-		if (mFollowRedirects)
-		{
-			mDetail->mCurlRequest->setopt(CURLOPT_FOLLOWLOCATION, 1);
-		}
-
-		// Set Accept-Encoding to allow response compression
-		mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
-		rv = true;
-		break;
-
-	case HTTP_PUT:
-		// Disable the expect http 1.1 extension. POST and PUT default
-		// to turning this on, and I am not too sure what it means.
-		addHeader(HTTP_OUT_HEADER_EXPECT);
-
-		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
-		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
-		rv = true;
-		break;
-
-	case HTTP_PATCH:
-		// Disable the expect http 1.1 extension. POST and PUT default
-		// to turning this on, and I am not too sure what it means.
-		addHeader(HTTP_OUT_HEADER_EXPECT);
-
-		mDetail->mCurlRequest->setopt(CURLOPT_UPLOAD, 1);
-		mDetail->mCurlRequest->setopt(CURLOPT_INFILESIZE, bytes);
-		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "PATCH");
-		rv = true;
-		break;
-
-	case HTTP_POST:
-		// Disable the expect http 1.1 extension. POST and PUT default
-		// to turning this on, and I am not too sure what it means.
-		addHeader(HTTP_OUT_HEADER_EXPECT);
-
-		// Disable the content type http header.
-		// *FIX: what should it be?
-		addHeader(HTTP_OUT_HEADER_CONTENT_TYPE);
-
-		// Set the handle for an http post
-		mDetail->mCurlRequest->setPost(NULL, bytes);
-
-		// Set Accept-Encoding to allow response compression
-		mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
-		rv = true;
-		break;
-
-	case HTTP_DELETE:
-		// Set the handle for an http delete
-		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "DELETE");
-		rv = true;
-		break;
-
-	case HTTP_COPY:
-		// Set the handle for an http copy
-		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "COPY");
-		rv = true;
-		break;
-
-	case HTTP_MOVE:
-		// Set the handle for an http move
-		mDetail->mCurlRequest->setoptString(CURLOPT_CUSTOMREQUEST, "MOVE");
-		// *NOTE: should we check for the Destination header?
-		rv = true;
-		break;
-
-	default:
-		LL_WARNS() << "Unhandled URLRequest action: " << mAction << LL_ENDL;
-		break;
-	}
-	if(rv)
-	{
-		mDetail->mCurlRequest->sendRequest(mDetail->mURL);
-	}
-	return rv;
-}
-
-// static
-size_t LLURLRequest::downCallback(
-	char* data,
-	size_t size,
-	size_t nmemb,
-	void* user)
-{
-	LLURLRequest* req = (LLURLRequest*)user;
-	if(STATE_WAITING_FOR_RESPONSE == req->mState)
-	{
-		req->mState = STATE_PROCESSING_RESPONSE;
-	}
-	U32 bytes = size * nmemb;
-	if (req->mDetail->mIsBodyLimitSet)
-	{
-		if (bytes > req->mDetail->mBodyLimit)
-		{
-			bytes = req->mDetail->mBodyLimit;
-			req->mDetail->mBodyLimit = 0;
-		}
-		else
-		{
-			req->mDetail->mBodyLimit -= bytes;
-		}
-	}
-
-	req->mDetail->mResponseBuffer->append(
-		req->mDetail->mChannels.out(),
-		(U8*)data,
-		bytes);
-	req->mResponseTransferedBytes += bytes;
-	req->mDetail->mByteAccumulator += bytes;
-	return bytes;
-}
-
-// static
-size_t LLURLRequest::upCallback(
-	char* data,
-	size_t size,
-	size_t nmemb,
-	void* user)
-{
-	LLURLRequest* req = (LLURLRequest*)user;
-	S32 bytes = llmin(
-		(S32)(size * nmemb),
-		req->mDetail->mResponseBuffer->countAfter(
-			req->mDetail->mChannels.in(),
-			req->mDetail->mLastRead));
-	req->mDetail->mLastRead =  req->mDetail->mResponseBuffer->readAfter(
-		req->mDetail->mChannels.in(),
-		req->mDetail->mLastRead,
-		(U8*)data,
-		bytes);
-	req->mRequestTransferedBytes += bytes;
-	return bytes;
-}
-
-static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
-{
-	const char* header_line = (const char*)data;
-	size_t header_len = size * nmemb;
-	LLURLRequestComplete* complete = (LLURLRequestComplete*)user;
-
-	if (!complete || !header_line)
-	{
-		return header_len;
-	}
-
-	// *TODO: This should be a utility in llstring.h: isascii()
-	for (size_t i = 0; i < header_len; ++i)
-	{
-		if (header_line[i] < 0)
-		{
-			return header_len;
-		}
-	}
-
-	std::string header(header_line, header_len);
-
-	// Per HTTP spec the first header line must be the status line.
-	if (header.substr(0,5) == "HTTP/")
-	{
-		std::string::iterator end = header.end();
-		std::string::iterator pos1 = std::find(header.begin(), end, ' ');
-		if (pos1 != end) ++pos1;
-		std::string::iterator pos2 = std::find(pos1, end, ' ');
-		if (pos2 != end) ++pos2;
-		std::string::iterator pos3 = std::find(pos2, end, '\r');
-
-		std::string version(header.begin(), pos1);
-		std::string status(pos1, pos2);
-		std::string reason(pos2, pos3);
-
-		S32 status_code = atoi(status.c_str());
-		if (status_code > 0)
-		{
-			complete->httpStatus(status_code, reason);
-			return header_len;
-		}
-	}
-
-	std::string::iterator sep = std::find(header.begin(),header.end(),':');
-
-	if (sep != header.end())
-	{
-		std::string key(header.begin(), sep);
-		std::string value(sep + 1, header.end());
-
-		key = utf8str_tolower(utf8str_trim(key));
-		value = utf8str_trim(value);
-
-		complete->header(key, value);
-	}
-	else
-	{
-		LLStringUtil::trim(header);
-		if (!header.empty())
-		{
-			LL_WARNS() << "Unable to parse header: " << header << LL_ENDL;
-		}
-	}
-
-	return header_len;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_EXTRACTOR("URL Extractor");
-/**
- * LLContextURLExtractor
- */
-// virtual
-LLIOPipe::EStatus LLContextURLExtractor::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_EXTRACTOR);
-	PUMP_DEBUG;
-	// The destination host is in the context.
-	if(context.isUndefined() || !mRequest)
-	{
-		return STATUS_PRECONDITION_NOT_MET;
-	}
-
-	// copy in to out, since this just extract the URL and does not
-	// actually change the data.
-	LLChangeChannel change(channels.in(), channels.out());
-	std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
-
-	// find the context url
-	if(context.has(CONTEXT_DEST_URI_SD_LABEL))
-	{
-		mRequest->setURL(context[CONTEXT_DEST_URI_SD_LABEL].asString());
-		return STATUS_DONE;
-	}
-	return STATUS_ERROR;
-}
-
-
-/**
- * LLURLRequestComplete
- */
-LLURLRequestComplete::LLURLRequestComplete() :
-	mRequestStatus(LLIOPipe::STATUS_ERROR)
-{
-}
-
-// virtual
-LLURLRequestComplete::~LLURLRequestComplete()
-{
-}
-
-//virtual 
-void LLURLRequestComplete::header(const std::string& header, const std::string& value)
-{
-}
-
-//virtual 
-void LLURLRequestComplete::complete(const LLChannelDescriptors& channels,
-		const buffer_ptr_t& buffer)
-{
-	if(STATUS_OK == mRequestStatus)
-	{
-		response(channels, buffer);
-	}
-	else
-	{
-		noResponse();
-	}
-}
-
-//virtual 
-void LLURLRequestComplete::response(const LLChannelDescriptors& channels,
-		const buffer_ptr_t& buffer)
-{
-	LL_WARNS() << "LLURLRequestComplete::response default implementation called"
-		<< LL_ENDL;
-}
-
-//virtual 
-void LLURLRequestComplete::noResponse()
-{
-	LL_WARNS() << "LLURLRequestComplete::noResponse default implementation called"
-		<< LL_ENDL;
-}
-
-void LLURLRequestComplete::responseStatus(LLIOPipe::EStatus status)
-{
-	mRequestStatus = status;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_URL_COMPLETE("URL Complete");
-// virtual
-LLIOPipe::EStatus LLURLRequestComplete::process_impl(
-	const LLChannelDescriptors& channels,
-	buffer_ptr_t& buffer,
-	bool& eos,
-	LLSD& context,
-	LLPumpIO* pump)
-{
-	LL_RECORD_BLOCK_TIME(FTM_PROCESS_URL_COMPLETE);
-	PUMP_DEBUG;
-	complete(channels, buffer);
-	return STATUS_OK;
-}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
deleted file mode 100755
index 88fccd4bf693c8d93e515e036be9327bf0a931f2..0000000000000000000000000000000000000000
--- a/indra/llmessage/llurlrequest.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/** 
- * @file llurlrequest.h
- * @author Phoenix
- * @date 2005-04-21
- * @brief Declaration of url based requests on pipes.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLURLREQUEST_H
-#define LL_LLURLREQUEST_H
-
-/** 
- * This file holds the declaration of useful classes for dealing with
- * url based client requests. 
- */
-
-#include <string>
-#include "lliopipe.h"
-#include "llchainio.h"
-#include "llerror.h"
-#include <openssl/x509_vfy.h>
-#include "llcurl.h"
-
-
-/**
- * External constants
- */
-extern const std::string CONTEXT_DEST_URI_SD_LABEL;
-extern const std::string CONTEXT_TRANSFERED_BYTES;
-
-class LLURLRequestDetail;
-
-class LLURLRequestComplete;
-
-/** 
- * @class LLURLRequest
- * @brief Class to handle url based requests.
- * @see LLIOPipe
- *
- * Currently, this class is implemented on top of curl. From the
- * vantage of a programmer using this class, you do not care so much,
- * but it's useful to know since in order to accomplish 'non-blocking'
- * behavior, we have to use a more expensive curl interface which can
- * still block if the server enters a half-accepted state. It would be
- * worth the time and effort to eventually port this to a raw client
- * socket.
- */
-class LLURLRequest : public LLIOPipe
-{
-	LOG_CLASS(LLURLRequest);
-public:
-	typedef int (* SSLCertVerifyCallback)(X509_STORE_CTX *ctx, void *param);
-
-	/** 
-	 * @brief Constructor.
-	 *
-	 * @param action One of the EHTTPMethod enumerations.
-	 */
-	LLURLRequest(EHTTPMethod action, bool follow_redirects = true);
-
-	/** 
-	 * @brief Constructor.
-	 *
-	 * @param action One of the EHTTPMethod enumerations.
-	 * @param url The url of the request. It should already be encoded.
-	 */
-	LLURLRequest(EHTTPMethod action, const std::string& url, bool follow_redirects = true);
-
-	/** 
-	 * @brief Destructor.
-	 */
-	virtual ~LLURLRequest();
-
-	/* @name Instance methods
-	 */
-	//@{
-	/** 
-	 * @brief Set the url for the request
-	 *
-	 * This method assumes the url is encoded appropriately for the
-	 * request. 
-	 * The url must be set somehow before the first call to process(),
-	 * or the url will not be set correctly.
-	 * 
-	 */
-	void setURL(const std::string& url);
-	const std::string& getURL() const;
-	/** 
-	 * @brief Add a header to the http post.
-	 *
-	 * This provides a raw interface if you know what kind of request you
-	 * will be making during construction of this instance. All
-	 * required headers will be automatically constructed, so this is
-	 * usually useful for encoding parameters.
-	 */
-	void addHeader(const std::string& header, const std::string& value = "");
-	void addHeaderRaw(const char* header);
-
-	/**
-	 * @brief Check remote server certificate signed by a known root CA.
-	 *
-	 * Set whether request will check that remote server
-	 * certificates are signed by a known root CA when using HTTPS.
-	 */
-	void setSSLVerifyCallback(SSLCertVerifyCallback callback, void * param);
-
-	
-	/**
-	 * @brief Return at most size bytes of body.
-	 *
-	 * If the body had more bytes than this limit, they will not be
-	 * returned and the connection closed.  In this case, STATUS_STOP
-	 * will be passed to responseStatus();
-	 */
-	void setBodyLimit(U32 size);
-
-	/** 
-	 * @brief Set a completion callback for this URLRequest.
-	 *
-	 * The callback is added to this URLRequet's pump when either the
-	 * entire buffer is known or an error like timeout or connection
-	 * refused has happened. In the case of a complete transfer, this
-	 * object builds a response chain such that the callback and the
-	 * next process consumer get to read the output.
-	 *
-	 * This setup is a little fragile since the url request consumer
-	 * might not just read the data - it may do a channel change,
-	 * which invalidates the input to the callback, but it works well
-	 * in practice.
-	 */
-	void setCallback(LLURLRequestComplete* callback);
-	//@}
-
-	/* @name LLIOPipe virtual implementations
-	 */
-
-    /**
-     * @ brief Turn off (or on) the CURLOPT_PROXY header.
-     */
-    void useProxy(bool use_proxy);
-
-    /**
-     * @ brief Set the CURLOPT_PROXY header to the given value.
-     */
-	void useProxy(const std::string& proxy);
-
-	/**
-	 * @brief Turn on cookie handling for this request with CURLOPT_COOKIEFILE.
-	 */
-	void allowCookies();
-
-	/*virtual*/ bool isValid() ;
-
-public:
-	/** 
-	 * @brief Give this pipe a chance to handle a generated error
-	 */
-	virtual EStatus handleError(EStatus status, LLPumpIO* pump);
-
-	
-protected:
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-
-protected:
-	enum EState
-	{
-		STATE_INITIALIZED,
-		STATE_WAITING_FOR_RESPONSE,
-		STATE_PROCESSING_RESPONSE,
-		STATE_HAVE_RESPONSE,
-	};
-	EState mState;
-	EHTTPMethod mAction;
-	bool mFollowRedirects;
-	LLURLRequestDetail* mDetail;
-	LLIOPipe::ptr_t mCompletionCallback;
-	S32 mRequestTransferedBytes;
-	S32 mResponseTransferedBytes;
-
-	static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param);
-	
-private:
-	/** 
-	 * @brief Initialize the object. Called during construction.
-	 */
-	void initialize();
-
-	/** 
-	 * @brief Handle action specific url request configuration.
-	 *
-	 * @return Returns true if this is configured.
-	 */
-	bool configure();
-
-	/** 
-	 * @brief Download callback method.
-	 */
- 	static size_t downCallback(
-		char* data,
-		size_t size,
-		size_t nmemb,
-		void* user);
-
-	/** 
-	 * @brief Upload callback method.
-	 */
- 	static size_t upCallback(
-		char* data,
-		size_t size,
-		size_t nmemb,
-		void* user);
-
-	/** 
-	 * @brief Declaration of unimplemented method to prevent copy
-	 * construction.
-	 */
-	LLURLRequest(const LLURLRequest&);
-};
-
-
-/** 
- * @class LLContextURLExtractor
- * @brief This class unpacks the url out of a agent usher service so
- * it can be packed into a LLURLRequest object.
- * @see LLIOPipe
- *
- * This class assumes that the context is a map that contains an entry
- * named CONTEXT_DEST_URI_SD_LABEL.
- */
-class LLContextURLExtractor : public LLIOPipe
-{
-public:
-	LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
-	~LLContextURLExtractor() {}
-
-protected:
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-
-protected:
-	LLURLRequest* mRequest;
-};
-
-
-/** 
- * @class LLURLRequestComplete
- * @brief Class which can optionally be used with an LLURLRequest to
- * get notification when the url request is complete.
- */
-class LLURLRequestComplete : public LLIOPipe
-{
-public:
-	
-	// Called once for each header received, except status lines
-	virtual void header(const std::string& header, const std::string& value);
-
-	// May be called more than once, particularly for redirects and proxy madness.
-	// Ex. a 200 for a connection to https through a proxy, followed by the "real" status
-	//     a 3xx for a redirect followed by a "real" status, or more redirects.
-	virtual void httpStatus(S32 status, const std::string& reason) { }
-
-	virtual void complete(
-		const LLChannelDescriptors& channels,
-		const buffer_ptr_t& buffer);
-
-	/** 
-	 * @brief This method is called when we got a valid response.
-	 *
-	 * It is up to class implementers to do something useful here.
-	 */
-	virtual void response(
-		const LLChannelDescriptors& channels,
-		const buffer_ptr_t& buffer);
-
-	/** 
-	 * @brief This method is called if there was no response.
-	 *
-	 * It is up to class implementers to do something useful here.
-	 */
-	virtual void noResponse();
-
-	/** 
-	 * @brief This method will be called by the LLURLRequest object.
-	 *
-	 * If this is set to STATUS_OK or STATUS_STOP, then the transfer
-	 * is asssumed to have worked. This will lead to calling response()
-	 * on the next call to process(). Otherwise, this object will call
-	 * noResponse() on the next call to process.
-	 * @param status The status of the URLRequest.
-	 */
-	void responseStatus(EStatus status);
-
-	// constructor & destructor.
-	LLURLRequestComplete();
-	virtual ~LLURLRequestComplete();
-
-protected:
-	/* @name LLIOPipe virtual implementations
-	 */
-	//@{
-	/** 
-	 * @brief Process the data in buffer
-	 */
-	virtual EStatus process_impl(
-		const LLChannelDescriptors& channels,
-		buffer_ptr_t& buffer,
-		bool& eos,
-		LLSD& context,
-		LLPumpIO* pump);
-	//@}
-
-	// value to note if we actually got the response. This value
-	// depends on correct usage from the LLURLRequest instance.
-	EStatus mRequestStatus;
-};
-
-#endif // LL_LLURLREQUEST_H
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index e9ce94ab3b62c1f97a404b7ac4d03cc0488bee39..2f4b47286d849b8cf5ae076397ca638e86ded099 100755
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -50,9 +50,7 @@
 #include "lldir.h"
 #include "llerror.h"
 #include "llfasttimer.h"
-#include "llhttpclient.h"
 #include "llhttpnodeadapter.h"
-#include "llhttpsender.h"
 #include "llmd5.h"
 #include "llmessagebuilder.h"
 #include "llmessageconfig.h"
@@ -77,6 +75,7 @@
 #include "v3math.h"
 #include "v4math.h"
 #include "lltransfertargetvfile.h"
+#include "llcorehttputil.h"
 
 // Constants
 //const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -97,45 +96,6 @@ class LLMessagePollInfo
 	apr_pollfd_t mPollFD;
 };
 
-namespace
-{
-	class LLFnPtrResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(LLFnPtrResponder);
-	public:
-		LLFnPtrResponder(void (*callback)(void **,S32), void **callbackData, const std::string& name) :
-			mCallback(callback),
-			mCallbackData(callbackData),
-			mMessageName(name)
-		{
-		}
-
-	protected:
-		virtual void httpFailure()
-		{
-			// don't spam when agent communication disconnected already
-			if (HTTP_GONE != getStatus())
-			{
-				LL_WARNS("Messaging") << "error for message " << mMessageName
-									  << " " << dumpResponse() << LL_ENDL;
-			}
-			// TODO: Map status in to useful error code.
-			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_TCP_TIMEOUT);
-		}
-		
-		virtual void httpSuccess()
-		{
-			if(NULL != mCallback) mCallback(mCallbackData, LL_ERR_NOERR);
-		}
-
-	private:
-
-		void (*mCallback)(void **,S32);    
-		void **mCallbackData;
-		std::string mMessageName;
-	};
-}
-
 class LLMessageHandlerBridge : public LLHTTPNode
 {
 	virtual bool validate(const std::string& name, LLSD& context) const
@@ -1129,29 +1089,6 @@ S32 LLMessageSystem::flushReliable(const LLHost &host)
 	return send_bytes;
 }
 
-LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& name)
-{
-	if(mSendReliable)
-	{
-		return new LLFnPtrResponder(
-			mReliablePacketParams.mCallback,
-			mReliablePacketParams.mCallbackData,
-			name);
-	}
-	else
-	{
-		// These messages aren't really unreliable, they just weren't
-		// explicitly sent as reliable, so they don't have a callback
-//		LL_WARNS("Messaging") << "LLMessageSystem::sendMessage: Sending unreliable "
-//				<< mMessageBuilder->getMessageName() << " message via HTTP"
-//				<< LL_ENDL;
-		return new LLFnPtrResponder(
-			NULL,
-			NULL,
-			name);
-	}
-}
-
 // This can be called from signal handlers,
 // so should should not use LL_INFOS().
 S32 LLMessageSystem::sendMessage(const LLHost &host)
@@ -1216,13 +1153,17 @@ S32 LLMessageSystem::sendMessage(const LLHost &host)
 	if(mMessageBuilder == mLLSDMessageBuilder)
 	{
 		LLSD message = mLLSDMessageBuilder->getMessage();
-		
-		const LLHTTPSender& sender = LLHTTPSender::getSender(host);
-		sender.send(
-			host,
-			mLLSDMessageBuilder->getMessageName(),
-			message,
-			createResponder(mLLSDMessageBuilder->getMessageName()));
+
+        UntrustedCallback_t cb = NULL;
+        if ((mSendReliable) && (mReliablePacketParams.mCallback))
+        {
+            cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+        }
+
+        LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+            boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this, 
+            host.getUntrustedSimulatorCap(), 
+            mLLSDMessageBuilder->getMessageName(), message, cb));
 
 		mSendReliable = FALSE;
 		mReliablePacketParams.clear();
@@ -1410,9 +1351,16 @@ S32 LLMessageSystem::sendMessage(
 		return 0;
 	}
 
-	const LLHTTPSender& sender = LLHTTPSender::getSender(host);
-	sender.send(host, name, message, createResponder(name));
-	return 1;
+    UntrustedCallback_t cb = NULL;
+    if ((mSendReliable) && (mReliablePacketParams.mCallback))
+    {
+        cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+    }
+
+    LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+            boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+            host.getUntrustedSimulatorCap(), name, message, cb));
+    return 1;
 }
 
 void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
@@ -1725,7 +1673,7 @@ LLHost LLMessageSystem::findHost(const U32 circuit_code)
 	}
 	else
 	{
-		return LLHost::invalid;
+		return LLHost();
 	}
 }
 
@@ -4055,6 +4003,36 @@ const LLHost& LLMessageSystem::getSender() const
 	return mLastSender;
 }
 
+void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+
+    if (url.empty())
+    {
+        LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
+        return;
+    }
+
+    LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
+    LLSD postData;
+    postData["message"] = message;
+    postData["body"] = body;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if ((callback) && (!callback.empty()))
+        callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
+}
+
+
 LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
 	gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
 
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 348b09b9923bbde5fe023c4d2df7a478af0969e5..133db620e68541e6deec77506027384bdc328186 100755
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -50,7 +50,6 @@
 #include "lltimer.h"
 #include "llpacketring.h"
 #include "llhost.h"
-#include "llcurl.h"
 #include "llhttpnode.h"
 //#include "llpacketack.h"
 #include "llsingleton.h"
@@ -60,6 +59,7 @@
 #include "llmessagesenderinterface.h"
 
 #include "llstoredmessage.h"
+#include "boost/function.hpp"
 
 const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
 const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -489,7 +489,6 @@ class LLMessageSystem : public LLMessageSenderInterface
 		void (*callback)(void **,S32), 
 		void ** callback_data);
 
-	LLCurl::ResponderPtr createResponder(const std::string& name);
 	S32		sendMessage(const LLHost &host);
 	S32		sendMessage(const U32 circuit);
 private:
@@ -740,6 +739,9 @@ class LLMessageSystem : public LLMessageSenderInterface
 	void receivedMessageFromTrustedSender();
 	
 private:
+    typedef boost::function<void(S32)>  UntrustedCallback_t;
+    void sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback);
+
 
 	bool mLastMessageFromTrustedMessageService;
 	
diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp
deleted file mode 100755
index e9ce116bb38cb2053ea266a26fbdfb30f34ff92f..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/llhttpclientadapter_test.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-/** 
- * @file llhttpclientadapter_test.cpp
- * @brief Tests for LLHTTPClientAdapter
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llhttpclientadapter.h"
-
-#include "../test/lltut.h"
-#include "llhttpclient.h"
-#include "llcurl_stub.cpp"
-
-float const HTTP_REQUEST_EXPIRY_SECS = 1.0F;
-
-std::vector<std::string> get_urls;
-std::vector< LLCurl::ResponderPtr > get_responders;
-void LLHTTPClient::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout, bool follow_redirects)
-{
-	get_urls.push_back(url);
-	get_responders.push_back(responder);
-}
-
-std::vector<std::string> put_urls;
-std::vector<LLSD> put_body;
-std::vector<LLSD> put_headers;
-std::vector<LLCurl::ResponderPtr> put_responders;
-
-void LLHTTPClient::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder, const LLSD& headers, const F32 timeout)
-{
-	put_urls.push_back(url);
-	put_responders.push_back(responder);
-	put_body.push_back(body);
-	put_headers.push_back(headers);
-
-}
-
-std::vector<std::string> delete_urls;
-std::vector<LLCurl::ResponderPtr> delete_responders;
-
-void LLHTTPClient::del(
-	const std::string& url,
-	LLCurl::ResponderPtr responder,
-	const LLSD& headers,
-	const F32 timeout)
-{
-	delete_urls.push_back(url);
-	delete_responders.push_back(responder);
-}
-
-namespace tut
-{
-	struct LLHTTPClientAdapterData
-	{
-		LLHTTPClientAdapterData()
-		{
-			get_urls.clear();
-			get_responders.clear();
-			put_urls.clear();
-			put_responders.clear();
-			put_body.clear();
-			put_headers.clear();
-			delete_urls.clear();
-			delete_responders.clear();
-		}
-	};
-
-	typedef test_group<LLHTTPClientAdapterData> factory;
-	typedef factory::object object;
-}
-
-namespace
-{
-	tut::factory tf("LLHTTPClientAdapterData");
-}
-
-namespace tut
-{
-	// Ensure we can create the object
-	template<> template<>
-	void object::test<1>()
-	{
-		LLHTTPClientAdapter adapter;
-	}
-
-	// Does the get pass the appropriate arguments to the LLHTTPClient
-	template<> template<>
-	void object::test<2>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		adapter.get("Made up URL", responder);
-		ensure_equals(get_urls.size(), 1);
-		ensure_equals(get_urls[0], "Made up URL");
-	}
-
-	// Ensure the responder matches the one passed to get
-	template<> template<>
-	void object::test<3>()
-	{
-		LLHTTPClientAdapter adapter;
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		adapter.get("Made up URL", responder);
-
-		ensure_equals(get_responders.size(), 1);
-		ensure_equals(get_responders[0].get(), responder.get());
-	}
-	
-	// Ensure the correct url is used in the put
-	template<> template<>
-	void object::test<4>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		LLSD body;
-		body["TestBody"] = "Foobar";
-
-		adapter.put("Made up URL", body, responder);
-		ensure_equals(put_urls.size(), 1);
-		ensure_equals(put_urls[0], "Made up URL");
-	}
-
-	// Ensure the correct responder is used by put
-	template<> template<>
-	void object::test<5>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		LLSD body;
-		body["TestBody"] = "Foobar";
-
-		adapter.put("Made up URL", body, responder);
-
-		ensure_equals(put_responders.size(), 1);
-		ensure_equals(put_responders[0].get(), responder.get());
-	}
-
-	// Ensure the message body is passed through the put properly
-	template<> template<>
-	void object::test<6>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		LLSD body;
-		body["TestBody"] = "Foobar";
-
-		adapter.put("Made up URL", body, responder);
-
-		ensure_equals(put_body.size(), 1);
-		ensure_equals(put_body[0]["TestBody"].asString(), "Foobar");
-	}
-
-	// Ensure that headers are passed through put properly
-	template<> template<>
-	void object::test<7>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		LLSD body = LLSD::emptyMap();
-		body["TestBody"] = "Foobar";
-
-		LLSD headers = LLSD::emptyMap();
-		headers["booger"] = "omg";
-
-		adapter.put("Made up URL", body, responder, headers);
-
-		ensure_equals("Header count", put_headers.size(), 1);
-		ensure_equals(
-			"First header",
-			put_headers[0]["booger"].asString(),
-			"omg");
-	}
-
-	// Ensure that del() passes appropriate arguments to the LLHTTPClient
-	template<> template<>
-	void object::test<8>()
-	{
-		LLHTTPClientAdapter adapter;
-
-		LLCurl::ResponderPtr responder = new LLCurl::Responder();
-
-		adapter.del("Made up URL", responder);
-
-		ensure_equals("URL count", delete_urls.size(), 1);
-		ensure_equals("Received URL", delete_urls[0], "Made up URL");
-
-		ensure_equals("Responder count", delete_responders.size(), 1);
-		//ensure_equals("Responder", delete_responders[0], responder);
-	}
-}
-
diff --git a/indra/llmessage/tests/llsdmessage_test.cpp b/indra/llmessage/tests/llsdmessage_test.cpp
deleted file mode 100755
index 44b024a83f28fe994e1d161f04a2e3e648dcd6dd..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/llsdmessage_test.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * @file   llsdmessage_test.cpp
- * @author Nat Goodspeed
- * @date   2008-12-22
- * @brief  Test of llsdmessage.h
- * 
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if LL_WINDOWS
-#pragma warning (disable : 4675) // "resolved by ADL" -- just as I want!
-#endif
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "llsdmessage.h"
-// STL headers
-#include <iostream>
-// std headers
-#include <stdexcept>
-#include <typeinfo>
-// external library headers
-// other Linden headers
-#include "../test/lltut.h"
-#include "../test/catch_and_store_what_in.h"
-#include "llsdserialize.h"
-#include "llevents.h"
-#include "stringize.h"
-#include "llhost.h"
-#include "tests/networkio.h"
-#include "tests/commtest.h"
-
-/*****************************************************************************
-*   TUT
-*****************************************************************************/
-namespace tut
-{
-    struct llsdmessage_data: public commtest_data
-    {
-        LLEventPump& httpPump;
-
-        llsdmessage_data():
-            httpPump(pumps.obtain("LLHTTPClient"))
-        {
-            LLCurl::initClass();
-            LLSDMessage::link();
-        }
-    };
-    typedef test_group<llsdmessage_data> llsdmessage_group;
-    typedef llsdmessage_group::object llsdmessage_object;
-    llsdmessage_group llsdmgr("llsdmessage");
-
-    template<> template<>
-    void llsdmessage_object::test<1>()
-    {
-        std::string threw;
-        // This should fail...
-        try
-        {
-            LLSDMessage localListener;
-        }
-        CATCH_AND_STORE_WHAT_IN(threw, LLEventPump::DupPumpName)
-        ensure("second LLSDMessage should throw", ! threw.empty());
-    }
-
-    template<> template<>
-    void llsdmessage_object::test<2>()
-    {
-        LLSD request, body;
-        body["data"] = "yes";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        bool threw = false;
-        try
-        {
-            httpPump.post(request);
-        }
-        catch (const LLSDMessage::ArgError&)
-        {
-            threw = true;
-        }
-        ensure("missing URL", threw);
-    }
-
-    template<> template<>
-    void llsdmessage_object::test<3>()
-    {
-        LLSD request, body;
-        body["data"] = "yes";
-        request["url"] = server + "got-message";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        httpPump.post(request);
-        ensure("got response", netio.pump());
-        ensure("success response", success);
-        ensure_equals(result["reply"].asString(), "success");
-
-        body["status"] = 499;
-        body["reason"] = "custom error message";
-        request["url"] = server + "fail";
-        request["payload"] = body;
-        httpPump.post(request);
-        ensure("got response", netio.pump());
-        ensure("failure response", ! success);
-        ensure_equals(result["status"].asInteger(), body["status"].asInteger());
-        ensure_equals(result["reason"].asString(),  body["reason"].asString());
-    }
-} // namespace tut
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp
deleted file mode 100755
index 4539e4a540cfd7a76a374d336493819e222ca2cd..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/lltesthttpclientadapter.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/** 
- * @file 
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#include "lltesthttpclientadapter.h"
-
-LLTestHTTPClientAdapter::LLTestHTTPClientAdapter()
-{
-}
-
-LLTestHTTPClientAdapter::~LLTestHTTPClientAdapter()
-{
-}
-
-void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder)
-{
-	mGetUrl.push_back(url);
-	mGetResponder.push_back(responder);
-}
-
-void LLTestHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)
-{
-	mPutUrl.push_back(url);
-	mPutBody.push_back(body);
-	mPutResponder.push_back(responder);
-}
-
-U32 LLTestHTTPClientAdapter::putCalls() const 
-{ 
-	return mPutUrl.size(); 
-}
-
-void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
-{
-	mGetUrl.push_back(url);
-	mGetHeaders.push_back(headers);
-	mGetResponder.push_back(responder);
-}
-
-
diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h
deleted file mode 100755
index c29cbb3a2a99648d6d82b5cd22f5c321b796e63a..0000000000000000000000000000000000000000
--- a/indra/llmessage/tests/lltesthttpclientadapter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/** 
- * @file 
- * @brief 
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-/* Macro Definitions */
-#ifndef LL_LLTESTHTTPCLIENTADAPTER_H
-#define LL_LLTESTHTTPCLIENTADAPTER_H
-
-
-#include "linden_common.h"
-#include "llhttpclientinterface.h"
-
-class LLTestHTTPClientAdapter : public LLHTTPClientInterface
-{
-public:
-	LLTestHTTPClientAdapter();
-	virtual ~LLTestHTTPClientAdapter();
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder);
-	virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers);
-
-	virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder);
-	U32 putCalls() const;
-
-	std::vector<LLSD> mPutBody;
-	std::vector<LLSD> mGetHeaders;
-	std::vector<std::string> mPutUrl;
-	std::vector<std::string> mGetUrl;
-	std::vector<LLCurl::ResponderPtr> mPutResponder;
-	std::vector<LLCurl::ResponderPtr> mGetResponder;
-};
-
-
-
-#endif //LL_LLSIMULATORPRESENCESENDER_H
-
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index d1475cf7342a2fb86751c6254c4c7952f4acad2b..dd2e806dda2ae942010336d3744b0af72cdf207a 100755
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -6,8 +6,10 @@ include(00-Common)
 include(LLCommon)
 include(LLMath)
 include(LLMessage)
+include(LLCoreHttp)
 include(LLXML)
 include(LLPhysicsExtensions)
+include(LLCharacter)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -16,6 +18,7 @@ include_directories(
     ${LLXML_INCLUDE_DIRS}
     ${LIBS_PREBUILT_DIR}/include/collada
     ${LIBS_PREBUILT_DIR}/include/collada/1.4
+    ${LLCHARACTER_INCLUDE_DIRS}
     )
 include_directories(SYSTEM
     ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -24,11 +27,13 @@ include_directories(SYSTEM
     )
 
 set(llprimitive_SOURCE_FILES
+    lldaeloader.cpp
     llmaterialid.cpp
     llmaterial.cpp
     llmaterialtable.cpp
     llmediaentry.cpp
     llmodel.cpp
+    llmodelloader.cpp
     llprimitive.cpp
     llprimtexturelist.cpp
     lltextureanim.cpp
@@ -40,16 +45,17 @@ set(llprimitive_SOURCE_FILES
 
 set(llprimitive_HEADER_FILES
     CMakeLists.txt
-
+    lldaeloader.h
     legacy_object_types.h
-    lllslconstants.h
     llmaterial.h
     llmaterialid.h
     llmaterialtable.h
     llmediaentry.h
     llmodel.h
+    llmodelloader.h
     llprimitive.h
     llprimtexturelist.h
+    lllslconstants.h
     lltextureanim.h
     lltextureentry.h
     lltreeparams.h
@@ -70,8 +76,12 @@ target_link_libraries(llprimitive
     ${LLCOMMON_LIBRARIES}
     ${LLMATH_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLXML_LIBRARIES}
     ${LLPHYSICSEXTENSIONS_LIBRARIES}
+    ${LLCHARACTER_LIBRARIES}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
     )
 
 
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c1b74b1fd7ee5cd96a5b2de9f07218b4dd2dcb62
--- /dev/null
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -0,0 +1,2436 @@
+/**
+ * @file lldaeloader.cpp
+ * @brief LLDAELoader class implementation
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#if LL_MSVC
+#pragma warning (disable : 4263)
+#pragma warning (disable : 4264)
+#endif
+#include "dae.h"
+#include "dom/domAsset.h"
+#include "dom/domBind_material.h"
+#include "dom/domCOLLADA.h"
+#include "dom/domConstants.h"
+#include "dom/domController.h"
+#include "dom/domEffect.h"
+#include "dom/domGeometry.h"
+#include "dom/domInstance_geometry.h"
+#include "dom/domInstance_material.h"
+#include "dom/domInstance_node.h"
+#include "dom/domInstance_effect.h"
+#include "dom/domMaterial.h"
+#include "dom/domMatrix.h"
+#include "dom/domNode.h"
+#include "dom/domProfile_COMMON.h"
+#include "dom/domRotate.h"
+#include "dom/domScale.h"
+#include "dom/domTranslate.h"
+#include "dom/domVisual_scene.h"
+#if LL_MSVC
+#pragma warning (default : 4263)
+#pragma warning (default : 4264)
+#endif
+
+#include <boost/lexical_cast.hpp>
+
+#include "lldaeloader.h"
+#include "llsdserialize.h"
+#include "lljoint.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+
+std::string colladaVersion[VERSIONTYPE_COUNT+1] = 
+{
+	"1.4.0",
+	"1.4.1",
+	"Unsupported"
+};
+
+static const std::string lod_suffix[LLModel::NUM_LODS] =
+{
+	"_LOD0",
+	"_LOD1",
+	"_LOD2",
+	"",
+	"_PHYS",
+};
+
+const U32 LIMIT_MATERIALS_OUTPUT = 12;
+
+bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
+	domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
+{
+	idx_stride = 0;
+
+	for (U32 j = 0; j < inputs.getCount(); ++j)
+	{
+		idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride);
+
+		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
+		{ //found vertex array
+			const domURIFragmentType& uri = inputs[j]->getSource();
+			daeElementRef elem = uri.getElement();
+			domVertices* vertices = (domVertices*) elem.cast();
+			if ( !vertices )
+			{
+				return false;
+			}
+
+			domInputLocal_Array& v_inp = vertices->getInput_array();
+
+
+			for (U32 k = 0; k < v_inp.getCount(); ++k)
+			{
+				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
+				{
+					pos_offset = inputs[j]->getOffset();
+
+					const domURIFragmentType& uri = v_inp[k]->getSource();
+					daeElementRef elem = uri.getElement();
+					pos_source = (domSource*) elem.cast();
+				}
+
+				if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0)
+				{
+					norm_offset = inputs[j]->getOffset();
+
+					const domURIFragmentType& uri = v_inp[k]->getSource();
+					daeElementRef elem = uri.getElement();
+					norm_source = (domSource*) elem.cast();
+				}
+			}
+		}
+
+		if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
+		{
+			//found normal array for this triangle list
+			norm_offset = inputs[j]->getOffset();
+			const domURIFragmentType& uri = inputs[j]->getSource();
+			daeElementRef elem = uri.getElement();
+			norm_source = (domSource*) elem.cast();
+		}
+		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
+		{ //found texCoords
+			tc_offset = inputs[j]->getOffset();
+			const domURIFragmentType& uri = inputs[j]->getSource();
+			daeElementRef elem = uri.getElement();
+			tc_source = (domSource*) elem.cast();
+		}
+	}
+
+	idx_stride += 1;
+
+	return true;
+}
+
+LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
+{
+	LLVolumeFace face;
+	std::vector<LLVolumeFace::VertexData> verts;
+	std::vector<U16> indices;
+	
+	const domInputLocalOffset_Array& inputs = tri->getInput_array();
+
+	S32 pos_offset = -1;
+	S32 tc_offset = -1;
+	S32 norm_offset = -1;
+
+	domSource* pos_source = NULL;
+	domSource* tc_source = NULL;
+	domSource* norm_source = NULL;
+
+	S32 idx_stride = 0;
+
+	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
+	{
+		return LLModel::BAD_ELEMENT;
+	}
+
+	if (!pos_source || !pos_source->getFloat_array())
+	{
+		LL_WARNS() << "Unable to process mesh without position data; invalid model;  invalid model." << LL_ENDL;
+		return LLModel::BAD_ELEMENT;
+	}
+
+	domPRef p = tri->getP();
+	domListOfUInts& idx = p->getValue();
+	
+	domListOfFloats  dummy ;
+	domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ;
+	domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ;
+	domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ;
+
+	if (pos_source)
+	{
+		if(v.getCount() == 0)
+		{
+			return LLModel::BAD_ELEMENT;
+		}
+
+		face.mExtents[0].set(v[0], v[1], v[2]);
+		face.mExtents[1].set(v[0], v[1], v[2]);
+	}
+	
+	LLVolumeFace::VertexMapData::PointMap point_map;
+	
+	for (U32 i = 0; i < idx.getCount(); i += idx_stride)
+	{
+		LLVolumeFace::VertexData cv;
+		if (pos_source)
+		{
+			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
+								v[idx[i+pos_offset]*3+1],
+								v[idx[i+pos_offset]*3+2]));
+		}
+
+		if (tc_source)
+		{
+			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
+								tc[idx[i+tc_offset]*2+1]);
+		}
+		
+		if (norm_source)
+		{
+			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
+								n[idx[i+norm_offset]*3+1],
+								n[idx[i+norm_offset]*3+2]));
+		}
+		
+		BOOL found = FALSE;
+			
+		LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
+		point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
+		
+		if (point_iter != point_map.end())
+		{
+			for (U32 j = 0; j < point_iter->second.size(); ++j)
+			{
+				// We have a matching loc
+				//
+				if ((point_iter->second)[j] == cv)
+				{
+					U16 shared_index	= (point_iter->second)[j].mIndex;
+
+					// Don't share verts within the same tri, degenerate
+					//
+					if ((indices.size() % 3) && (indices[indices.size()-1] != shared_index))
+					{
+						found = true;
+						indices.push_back(shared_index);
+					}
+					break;
+				}
+			}
+		}
+
+		if (!found)
+		{
+			update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
+			verts.push_back(cv);
+			if (verts.size() >= 65535)
+			{
+				//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
+				return LLModel::VERTEX_NUMBER_OVERFLOW ;
+			}
+			U16 index = (U16) (verts.size()-1);
+			indices.push_back(index);
+
+			LLVolumeFace::VertexMapData d;
+			d.setPosition(cv.getPosition());
+			d.mTexCoord = cv.mTexCoord;
+			d.setNormal(cv.getNormal());
+			d.mIndex = index;
+			if (point_iter != point_map.end())
+			{
+				point_iter->second.push_back(d);
+			}
+			else
+			{
+				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
+			}
+		}
+
+		if (indices.size()%3 == 0 && verts.size() >= 65532)
+		{
+			std::string material;
+
+			if (tri->getMaterial())
+			{
+				material = std::string(tri->getMaterial());
+			}
+
+			materials.push_back(material);
+			face_list.push_back(face);
+			face_list.rbegin()->fillFromLegacyData(verts, indices);
+			LLVolumeFace& new_face = *face_list.rbegin();
+			if (!norm_source)
+			{
+				//ll_aligned_free_16(new_face.mNormals);
+				new_face.mNormals = NULL;
+			}
+
+			if (!tc_source)
+			{
+				//ll_aligned_free_16(new_face.mTexCoords);
+				new_face.mTexCoords = NULL;
+			}
+
+			face = LLVolumeFace();
+			point_map.clear();
+		}
+	}
+
+	if (!verts.empty())
+	{
+		std::string material;
+
+		if (tri->getMaterial())
+		{
+			material = std::string(tri->getMaterial());
+		}
+		
+		materials.push_back(material);
+		face_list.push_back(face);
+
+		face_list.rbegin()->fillFromLegacyData(verts, indices);
+		LLVolumeFace& new_face = *face_list.rbegin();
+		if (!norm_source)
+		{
+			//ll_aligned_free_16(new_face.mNormals);
+			new_face.mNormals = NULL;
+		}
+
+		if (!tc_source)
+		{
+			//ll_aligned_free_16(new_face.mTexCoords);
+			new_face.mTexCoords = NULL;
+		}
+	}
+
+	return LLModel::NO_ERRORS ;
+}
+
+LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly)
+{
+	domPRef p = poly->getP();
+	domListOfUInts& idx = p->getValue();
+
+	if (idx.getCount() == 0)
+	{
+		return LLModel::NO_ERRORS ;
+	}
+
+	const domInputLocalOffset_Array& inputs = poly->getInput_array();
+
+
+	domListOfUInts& vcount = poly->getVcount()->getValue();
+	
+	S32 pos_offset = -1;
+	S32 tc_offset = -1;
+	S32 norm_offset = -1;
+
+	domSource* pos_source = NULL;
+	domSource* tc_source = NULL;
+	domSource* norm_source = NULL;
+
+	S32 idx_stride = 0;
+
+	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
+	{
+		return LLModel::BAD_ELEMENT;
+	}
+
+	LLVolumeFace face;
+
+	std::vector<U16> indices;
+	std::vector<LLVolumeFace::VertexData> verts;
+
+	domListOfFloats v;
+	domListOfFloats tc;
+	domListOfFloats n;
+
+	if (pos_source)
+	{
+		v = pos_source->getFloat_array()->getValue();
+		face.mExtents[0].set(v[0], v[1], v[2]);
+		face.mExtents[1].set(v[0], v[1], v[2]);
+	}
+
+	if (tc_source)
+	{
+		tc = tc_source->getFloat_array()->getValue();
+	}
+
+	if (norm_source)
+	{
+		n = norm_source->getFloat_array()->getValue();
+	}
+	
+	LLVolumeFace::VertexMapData::PointMap point_map;
+
+	U32 cur_idx = 0;
+	for (U32 i = 0; i < vcount.getCount(); ++i)
+	{ //for each polygon
+		U32 first_index = 0;
+		U32 last_index = 0;
+		for (U32 j = 0; j < vcount[i]; ++j)
+		{ //for each vertex
+
+			LLVolumeFace::VertexData cv;
+
+			if (pos_source)
+			{
+				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
+									v[idx[cur_idx+pos_offset]*3+1],
+									v[idx[cur_idx+pos_offset]*3+2]);
+				if (!cv.getPosition().isFinite3())
+				{
+					LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL;
+					return LLModel::BAD_ELEMENT;
+				}
+			}
+
+			if (tc_source)
+			{
+				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
+									tc[idx[cur_idx+tc_offset]*2+1]);
+			}
+			
+			if (norm_source)
+			{
+				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
+									n[idx[cur_idx+norm_offset]*3+1],
+									n[idx[cur_idx+norm_offset]*3+2]);
+
+				if (!cv.getNormal().isFinite3())
+				{
+					LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL;
+					return LLModel::BAD_ELEMENT;
+				}
+			}
+			
+			cur_idx += idx_stride;
+			
+			BOOL found = FALSE;
+				
+			LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
+			LLVector3 pos3(cv.getPosition().getF32ptr());
+			point_iter = point_map.find(pos3);
+			
+			if (point_iter != point_map.end())
+			{
+				for (U32 k = 0; k < point_iter->second.size(); ++k)
+				{
+					if ((point_iter->second)[k] == cv)
+					{
+						found = TRUE;
+						U32 index = (point_iter->second)[k].mIndex;
+						if (j == 0)
+						{
+							first_index = index;
+						}
+						else if (j == 1)
+						{
+							last_index = index;
+						}
+						else
+						{
+							// if these are the same, we have a very, very skinny triangle (coincident verts on one or more edges)
+							//
+							llassert((first_index != last_index) && (last_index != index) && (first_index != index));
+							indices.push_back(first_index);
+							indices.push_back(last_index);
+							indices.push_back(index);
+							last_index = index;
+						}
+
+						break;
+					}
+				}
+			}
+
+			if (!found)
+			{
+				update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
+				verts.push_back(cv);
+				if (verts.size() >= 65535)
+				{
+					//llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
+					return LLModel::VERTEX_NUMBER_OVERFLOW ;
+				}
+				U16 index = (U16) (verts.size()-1);
+			
+				if (j == 0)
+				{
+					first_index = index;
+				}
+				else if (j == 1)
+				{
+					last_index = index;
+				}
+				else
+				{
+					// detect very skinny degenerate triangles with collapsed edges
+					//
+					llassert((first_index != last_index) && (last_index != index) && (first_index != index));
+					indices.push_back(first_index);
+					indices.push_back(last_index);
+					indices.push_back(index);
+					last_index = index;
+				}	
+
+				LLVolumeFace::VertexMapData d;
+				d.setPosition(cv.getPosition());
+				d.mTexCoord = cv.mTexCoord;
+				d.setNormal(cv.getNormal());
+				d.mIndex = index;
+				if (point_iter != point_map.end())
+				{
+					point_iter->second.push_back(d);
+				}
+				else
+				{
+					point_map[pos3].push_back(d);
+				}
+			}
+
+			if (indices.size()%3 == 0 && indices.size() >= 65532)
+			{
+				std::string material;
+
+				if (poly->getMaterial())
+				{
+					material = std::string(poly->getMaterial());
+				}
+
+				materials.push_back(material);
+				face_list.push_back(face);
+				face_list.rbegin()->fillFromLegacyData(verts, indices);
+				LLVolumeFace& new_face = *face_list.rbegin();
+				if (!norm_source)
+				{
+					//ll_aligned_free_16(new_face.mNormals);
+					new_face.mNormals = NULL;
+				}
+
+				if (!tc_source)
+				{
+					//ll_aligned_free_16(new_face.mTexCoords);
+					new_face.mTexCoords = NULL;
+				}
+
+				face = LLVolumeFace();
+				verts.clear();
+				indices.clear();
+				point_map.clear();
+			}
+		}
+	}
+
+	if (!verts.empty())
+	{
+		std::string material;
+
+		if (poly->getMaterial())
+		{
+			material = std::string(poly->getMaterial());
+		}
+	
+		materials.push_back(material);
+		face_list.push_back(face);
+		face_list.rbegin()->fillFromLegacyData(verts, indices);
+
+		LLVolumeFace& new_face = *face_list.rbegin();
+		if (!norm_source)
+		{
+			//ll_aligned_free_16(new_face.mNormals);
+			new_face.mNormals = NULL;
+		}
+
+		if (!tc_source)
+		{
+			//ll_aligned_free_16(new_face.mTexCoords);
+			new_face.mTexCoords = NULL;
+		}
+	}
+
+	return LLModel::NO_ERRORS ;
+}
+
+LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly)
+{
+	LLVolumeFace face;
+	std::vector<U16> indices;
+	std::vector<LLVolumeFace::VertexData> verts;
+
+	const domInputLocalOffset_Array& inputs = poly->getInput_array();
+
+	S32 v_offset = -1;
+	S32 n_offset = -1;
+	S32 t_offset = -1;
+
+	domListOfFloats* v = NULL;
+	domListOfFloats* n = NULL;
+	domListOfFloats* t = NULL;
+	
+	U32 stride = 0;
+	for (U32 i = 0; i < inputs.getCount(); ++i)
+	{
+		stride = llmax((U32) inputs[i]->getOffset()+1, stride);
+
+		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0)
+		{ //found vertex array
+			v_offset = inputs[i]->getOffset();
+
+			const domURIFragmentType& uri = inputs[i]->getSource();
+			daeElementRef elem = uri.getElement();
+			domVertices* vertices = (domVertices*) elem.cast();
+			if (!vertices)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+			domInputLocal_Array& v_inp = vertices->getInput_array();
+
+			for (U32 k = 0; k < v_inp.getCount(); ++k)
+			{
+				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
+				{
+					const domURIFragmentType& uri = v_inp[k]->getSource();
+					daeElementRef elem = uri.getElement();
+					domSource* src = (domSource*) elem.cast();
+					if (!src)
+					{
+						return LLModel::BAD_ELEMENT;
+					}
+					v = &(src->getFloat_array()->getValue());
+				}
+			}
+		}
+		else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0)
+		{
+			n_offset = inputs[i]->getOffset();
+			//found normal array for this triangle list
+			const domURIFragmentType& uri = inputs[i]->getSource();
+			daeElementRef elem = uri.getElement();
+			domSource* src = (domSource*) elem.cast();
+			if (!src)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+			n = &(src->getFloat_array()->getValue());
+		}
+		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
+		{ //found texCoords
+			t_offset = inputs[i]->getOffset();
+			const domURIFragmentType& uri = inputs[i]->getSource();
+			daeElementRef elem = uri.getElement();
+			domSource* src = (domSource*) elem.cast();
+			if (!src)
+			{
+				return LLModel::BAD_ELEMENT;
+			}
+			t = &(src->getFloat_array()->getValue());
+		}
+	}
+
+	domP_Array& ps = poly->getP_array();
+
+	//make a triangle list in <verts>
+	for (U32 i = 0; i < ps.getCount(); ++i)
+	{ //for each polygon
+		domListOfUInts& idx = ps[i]->getValue();
+		for (U32 j = 0; j < idx.getCount()/stride; ++j)
+		{ //for each vertex
+			if (j > 2)
+			{
+				U32 size = verts.size();
+				LLVolumeFace::VertexData v0 = verts[size-3];
+				LLVolumeFace::VertexData v1 = verts[size-1];
+
+				verts.push_back(v0);
+				verts.push_back(v1);
+			}
+
+			LLVolumeFace::VertexData vert;
+
+
+			if (v)
+			{
+				U32 v_idx = idx[j*stride+v_offset]*3;
+				v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount());
+				vert.getPosition().set(v->get(v_idx),
+								v->get(v_idx+1),
+								v->get(v_idx+2));
+			}
+			
+			//bounds check n and t lookups because some FBX to DAE converters
+			//use negative indices and empty arrays to indicate data does not exist
+			//for a particular channel
+			if (n && n->getCount() > 0)
+			{
+				U32 n_idx = idx[j*stride+n_offset]*3;
+				n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount());
+				vert.getNormal().set(n->get(n_idx),
+								n->get(n_idx+1),
+								n->get(n_idx+2));
+			}
+			else
+			{
+				vert.getNormal().clear();
+			}
+
+			
+			if (t && t->getCount() > 0)
+			{
+				U32 t_idx = idx[j*stride+t_offset]*2;
+				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
+				vert.mTexCoord.setVec(t->get(t_idx),
+								t->get(t_idx+1));								
+			}
+			else
+			{
+				vert.mTexCoord.clear();
+			}
+
+						
+			verts.push_back(vert);
+		}
+	}
+
+	if (verts.empty())
+	{
+		return LLModel::NO_ERRORS;
+	}
+
+	face.mExtents[0] = verts[0].getPosition();
+	face.mExtents[1] = verts[0].getPosition();
+	
+	//create a map of unique vertices to indices
+	std::map<LLVolumeFace::VertexData, U32> vert_idx;
+
+	U32 cur_idx = 0;
+	for (U32 i = 0; i < verts.size(); ++i)
+	{
+		std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]);
+		if (iter == vert_idx.end())
+		{
+			vert_idx[verts[i]] = cur_idx++;
+		}
+	}
+
+	//build vertex array from map
+	std::vector<LLVolumeFace::VertexData> new_verts;
+	new_verts.resize(vert_idx.size());
+
+	for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter)
+	{
+		new_verts[iter->second] = iter->first;
+		update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition());
+	}
+
+	//build index array from map
+	indices.resize(verts.size());
+
+	for (U32 i = 0; i < verts.size(); ++i)
+	{
+		indices[i] = vert_idx[verts[i]];
+		llassert(!i || (indices[i-1] != indices[i]));
+	}
+
+	// DEBUG just build an expanded triangle list
+	/*for (U32 i = 0; i < verts.size(); ++i)
+	{
+		indices.push_back((U16) i);
+		update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition());
+	}*/
+
+    if (!new_verts.empty())
+	{
+		std::string material;
+
+		if (poly->getMaterial())
+		{
+			material = std::string(poly->getMaterial());
+		}
+
+		materials.push_back(material);
+		face_list.push_back(face);
+		face_list.rbegin()->fillFromLegacyData(new_verts, indices);
+
+		LLVolumeFace& new_face = *face_list.rbegin();
+		if (!n)
+		{
+			//ll_aligned_free_16(new_face.mNormals);
+			new_face.mNormals = NULL;
+		}
+
+		if (!t)
+		{
+			//ll_aligned_free_16(new_face.mTexCoords);
+			new_face.mTexCoords = NULL;
+		}
+	}
+
+	return LLModel::NO_ERRORS ;
+}
+
+//-----------------------------------------------------------------------------
+// LLDAELoader
+//-----------------------------------------------------------------------------
+LLDAELoader::LLDAELoader(
+	std::string				filename,
+	S32						lod,
+	load_callback_t		load_cb,
+	joint_lookup_func_t	joint_lookup_func,
+	texture_load_func_t	texture_load_func,
+	state_callback_t		state_cb,
+	void*						opaque_userdata,
+	JointTransformMap&	jointMap,
+	JointSet&				jointsFromNodes,
+	U32					modelLimit)
+: LLModelLoader(
+		filename,
+		lod,
+		load_cb,
+		joint_lookup_func,
+		texture_load_func,
+		state_cb,
+		opaque_userdata,
+		jointMap,
+		jointsFromNodes),
+mGeneratedModelLimit(modelLimit)
+{
+}
+
+LLDAELoader::~LLDAELoader()
+{
+}
+
+struct ModelSort
+{
+	bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs)
+	{
+        if (lhs->mSubmodelID < rhs->mSubmodelID)
+        {
+            return true;
+        }
+		return LLStringUtil::compareInsensitive(lhs->mLabel, rhs->mLabel) < 0;
+	}
+};
+
+bool LLDAELoader::OpenFile(const std::string& filename)
+{
+	//no suitable slm exists, load from the .dae file
+	DAE dae;
+	domCOLLADA* dom = dae.open(filename);
+	
+	if (!dom)
+	{
+		LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL;
+		setLoadState( ERROR_PARSING );
+		return false;
+	}
+	//Dom version
+	daeString domVersion = dae.getDomVersion();
+	std::string sldom(domVersion);
+	LL_INFOS()<<"Collada Importer Version: "<<sldom<<LL_ENDL;
+	//Dae version
+	domVersionType docVersion = dom->getVersion();
+	//0=1.4
+	//1=1.4.1
+	//2=Currently unsupported, however may work
+	if (docVersion > 1 ) 
+	{ 
+		docVersion = VERSIONTYPE_COUNT;
+	}
+	LL_INFOS()<<"Dae version "<<colladaVersion[docVersion]<<LL_ENDL;
+	
+	
+	daeDatabase* db = dae.getDatabase();
+	
+	daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
+	
+	daeDocument* doc = dae.getDoc(mFilename);
+	if (!doc)
+	{
+		LL_WARNS() << "can't find internal doc" << LL_ENDL;
+		return false;
+	}
+	
+	daeElement* root = doc->getDomRoot();
+	if (!root)
+	{
+		LL_WARNS() << "document has no root" << LL_ENDL;
+		return false;
+	}
+	
+	//Verify some basic properties of the dae
+	//1. Basic validity check on controller 
+	U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
+	bool result = false;
+	for ( int i=0; i<controllerCount; ++i )
+	{
+		domController* pController = NULL;
+		db->getElement( (daeElement**) &pController, i , NULL, "controller" );
+		result = verifyController( pController );
+		if (!result)
+		{
+			LL_INFOS() << "Could not verify controller" << LL_ENDL;
+			setLoadState( ERROR_PARSING );
+			return true;
+		}
+	}
+
+
+	//get unit scale
+	mTransform.setIdentity();
+	
+	domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID())));
+
+	if (unit)
+	{
+		F32 meter = unit->getMeter();
+		mTransform.mMatrix[0][0] = meter;
+		mTransform.mMatrix[1][1] = meter;
+		mTransform.mMatrix[2][2] = meter;
+	}
+	
+	//get up axis rotation
+	LLMatrix4 rotation;
+	
+	domUpAxisType up = UPAXISTYPE_Y_UP;  // default is Y_UP
+	domAsset::domUp_axis* up_axis =
+	daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID())));
+	
+	if (up_axis)
+	{
+		up = up_axis->getValue();
+	}
+	
+	if (up == UPAXISTYPE_X_UP)
+	{
+		rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
+	}
+	else if (up == UPAXISTYPE_Y_UP)
+	{
+		rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
+	}
+	
+	rotation *= mTransform;
+	mTransform = rotation;
+
+	mTransform.condition();	
+
+	U32 submodel_limit = count > 0 ? mGeneratedModelLimit/count : 0;
+	for (daeInt idx = 0; idx < count; ++idx)
+	{ //build map of domEntities to LLModel
+		domMesh* mesh = NULL;
+		db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
+		
+		if (mesh)
+		{
+
+			std::vector<LLModel*> models;
+
+			loadModelsFromDomMesh(mesh, models, submodel_limit);
+
+			std::vector<LLModel*>::iterator i;
+			i = models.begin();
+			while (i != models.end())
+			{
+				LLModel* mdl = *i;
+				if(mdl->getStatus() != LLModel::NO_ERRORS)
+				{
+					setLoadState(ERROR_MODEL + mdl->getStatus()) ;
+					return false; //abort
+				}
+
+				if (mdl && validate_model(mdl))
+				{
+					mModelList.push_back(mdl);
+					mModelsMap[mesh].push_back(mdl);
+				}
+				i++;
+			}
+		}
+	}
+
+	std::sort(mModelList.begin(), mModelList.end(), ModelSort());
+
+	model_list::iterator model_iter = mModelList.begin();
+	while (model_iter != mModelList.end())
+	{
+		LLModel* mdl = *model_iter;
+		U32 material_count = mdl->mMaterialList.size();
+		LL_INFOS() << "Importing " << mdl->mLabel << " model with " << material_count << " material references" << LL_ENDL;
+		std::vector<std::string>::iterator mat_iter = mdl->mMaterialList.begin();
+		std::vector<std::string>::iterator end_iter = material_count > LIMIT_MATERIALS_OUTPUT
+														? mat_iter + LIMIT_MATERIALS_OUTPUT
+														: mdl->mMaterialList.end();
+		while (mat_iter != end_iter)
+		{
+			LL_INFOS() << mdl->mLabel << " references " << (*mat_iter) << LL_ENDL;
+			mat_iter++;
+		}
+		model_iter++;
+	}
+
+	count = db->getElementCount(NULL, COLLADA_TYPE_SKIN);
+	for (daeInt idx = 0; idx < count; ++idx)
+	{ //add skinned meshes as instances
+		domSkin* skin = NULL;
+		db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
+		
+		if (skin)
+		{
+			domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
+			
+			if (geom)
+			{
+				domMesh* mesh = geom->getMesh();
+				if (mesh)
+				{
+					std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();
+					while (i != mModelsMap[mesh].end())
+					{
+						LLPointer<LLModel> mdl = *i;
+						LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin);
+						i++;
+					}
+				}
+			}
+		}
+	}
+
+	LL_INFOS()<< "Collada skins processed: " << count <<LL_ENDL;
+
+	daeElement* scene = root->getDescendant("visual_scene");
+	
+	if (!scene)
+	{
+		LL_WARNS() << "document has no visual_scene" << LL_ENDL;
+		setLoadState( ERROR_PARSING );
+		return true;
+	}
+	
+	setLoadState( DONE );
+
+	bool badElement = false;
+	
+	processElement( scene, badElement, &dae );
+	
+	if ( badElement )
+	{
+		LL_INFOS()<<"Scene could not be parsed"<<LL_ENDL;
+		setLoadState( ERROR_PARSING );
+	}
+	
+	return true;
+}
+
+void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, domMesh* mesh, domSkin* skin)
+{
+	llassert(model && dae && mesh && skin);
+
+	if (model)
+	{
+		LLVector3 mesh_scale_vector;
+		LLVector3 mesh_translation_vector;
+		model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
+
+		LLMatrix4 normalized_transformation;
+		normalized_transformation.setTranslation(mesh_translation_vector);
+
+		LLMatrix4 mesh_scale;
+		mesh_scale.initScale(mesh_scale_vector);
+		mesh_scale *= normalized_transformation;
+		normalized_transformation = mesh_scale;
+
+		glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
+		inv_mat = inv_mat.inverse();
+		LLMatrix4 inverse_normalized_transformation(inv_mat.m);
+
+		domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
+
+		if (bind_mat)
+		{ //get bind shape matrix
+			domFloat4x4& dom_value = bind_mat->getValue();
+
+			LLMeshSkinInfo& skin_info = model->mSkinInfo;
+
+			for (int i = 0; i < 4; i++)
+			{
+				for(int j = 0; j < 4; j++)
+				{
+					skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
+				}
+			}
+
+			LLMatrix4 trans = normalized_transformation;
+			trans *= skin_info.mBindShapeMatrix;
+			skin_info.mBindShapeMatrix = trans;							
+		}
+
+
+		//Some collada setup for accessing the skeleton
+		daeElement* pElement = 0;
+		dae->getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
+
+		//Try to get at the skeletal instance controller
+		domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
+		bool missingSkeletonOrScene = false;
+
+		//If no skeleton, do a breadth-first search to get at specific joints
+		bool rootNode = false;
+
+		//Need to test for a skeleton that does not have a root node
+		//This occurs when your instance controller does not have an associated scene 
+		if ( pSkeleton )
+		{
+			daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
+			if ( pSkeletonRootNode )
+			{
+				rootNode = true;
+			}
+
+		}
+		if ( !pSkeleton || !rootNode )
+		{
+			daeElement* pScene = root->getDescendant("visual_scene");
+			if ( !pScene )
+			{
+				LL_WARNS()<<"No visual scene - unable to parse bone offsets "<<LL_ENDL;
+				missingSkeletonOrScene = true;
+			}
+			else
+			{
+				//Get the children at this level
+				daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
+				S32 childCount = children.getCount();
+
+				//Process any children that are joints
+				//Not all children are joints, some code be ambient lights, cameras, geometry etc..
+				for (S32 i = 0; i < childCount; ++i)
+				{
+					domNode* pNode = daeSafeCast<domNode>(children[i]);
+					if ( isNodeAJoint( pNode ) )
+					{
+						processJointNode( pNode, mJointList );
+					}
+				}
+			}
+		}
+		else
+			//Has Skeleton
+		{
+			//Get the root node of the skeleton
+			daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
+			if ( pSkeletonRootNode )
+			{
+				//Once we have the root node - start acccessing it's joint components
+				const int jointCnt = mJointMap.size();
+				JointMap :: const_iterator jointIt = mJointMap.begin();
+
+				//Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
+				for ( int i=0; i<jointCnt; ++i, ++jointIt )
+				{
+					//Build a joint for the resolver to work with
+					char str[64]={0};
+					sprintf(str,"./%s",(*jointIt).first.c_str() );
+					//LL_WARNS()<<"Joint "<< str <<LL_ENDL;
+
+					//Setup the resolver
+					daeSIDResolver resolver( pSkeletonRootNode, str );
+
+					//Look for the joint
+					domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
+					if ( pJoint )
+					{
+						//Pull out the translate id and store it in the jointTranslations map
+						daeSIDResolver jointResolverA( pJoint, "./translate" );
+						domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+						daeSIDResolver jointResolverB( pJoint, "./location" );
+						domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
+
+						LLMatrix4 workingTransform;
+
+						//Translation via SID
+						if ( pTranslateA )
+						{
+							extractTranslation( pTranslateA, workingTransform );
+						}
+						else
+							if ( pTranslateB )
+							{
+								extractTranslation( pTranslateB, workingTransform );
+							}
+							else
+							{
+								//Translation via child from element
+								daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" );
+								if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() )
+								{
+									LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
+									missingSkeletonOrScene = true;
+								}
+								else
+									if ( pTranslateElement )
+									{
+										extractTranslationViaElement( pTranslateElement, workingTransform );
+									}
+									else
+									{
+										extractTranslationViaSID( pJoint, workingTransform );
+									}
+
+							}
+
+							//Store the joint transform w/respect to it's name.
+							mJointList[(*jointIt).second.c_str()] = workingTransform;
+					}
+				}
+
+				//If anything failed in regards to extracting the skeleton, joints or translation id,
+				//mention it
+				if ( missingSkeletonOrScene  )
+				{
+					LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL;
+				}
+			}//got skeleton?
+		}
+
+
+		domSkin::domJoints* joints = skin->getJoints();
+
+		domInputLocal_Array& joint_input = joints->getInput_array();
+
+		for (size_t i = 0; i < joint_input.getCount(); ++i)
+		{
+			domInputLocal* input = joint_input.get(i);
+			xsNMTOKEN semantic = input->getSemantic();
+
+			if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0)
+			{ //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames
+				daeElement* elem = input->getSource().getElement();
+
+				domSource* source = daeSafeCast<domSource>(elem);
+				if (source)
+				{
+
+
+					domName_array* names_source = source->getName_array();
+
+					if (names_source)
+					{
+						domListOfNames &names = names_source->getValue();
+
+						for (size_t j = 0; j < names.getCount(); ++j)
+						{
+							std::string name(names.get(j));
+							if (mJointMap.find(name) != mJointMap.end())
+							{
+								name = mJointMap[name];
+							}
+							model->mSkinInfo.mJointNames.push_back(name);
+							model->mSkinInfo.mJointMap[name] = j;
+						}
+					}
+					else
+					{
+						domIDREF_array* names_source = source->getIDREF_array();
+						if (names_source)
+						{
+							xsIDREFS& names = names_source->getValue();
+
+							for (size_t j = 0; j < names.getCount(); ++j)
+							{
+								std::string name(names.get(j).getID());
+								if (mJointMap.find(name) != mJointMap.end())
+								{
+									name = mJointMap[name];
+								}
+								model->mSkinInfo.mJointNames.push_back(name);
+								model->mSkinInfo.mJointMap[name] = j;
+							}
+						}
+					}
+				}
+			}
+			else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0)
+			{ //found inv_bind_matrix array, fill model->mInvBindMatrix
+				domSource* source = daeSafeCast<domSource>(input->getSource().getElement());
+				if (source)
+				{
+					domFloat_array* t = source->getFloat_array();
+					if (t)
+					{
+						domListOfFloats& transform = t->getValue();
+						S32 count = transform.getCount()/16;
+
+						for (S32 k = 0; k < count; ++k)
+						{
+							LLMatrix4 mat;
+
+							for (int i = 0; i < 4; i++)
+							{
+								for(int j = 0; j < 4; j++)
+								{
+									mat.mMatrix[i][j] = transform[k*16 + i + j*4];
+								}
+							}
+
+							model->mSkinInfo.mInvBindMatrix.push_back(mat);											
+						}
+					}
+				}
+			}
+		}
+
+		//Now that we've parsed the joint array, let's determine if we have a full rig
+		//(which means we have all the joint sthat are required for an avatar versus
+		//a skinned asset attached to a node in a file that contains an entire skeleton,
+		//but does not use the skeleton).						
+		buildJointToNodeMappingFromScene( root );
+		critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames );
+
+		if ( !missingSkeletonOrScene )
+		{
+			//Set the joint translations on the avatar - if it's a full mapping
+			//The joints are reset in the dtor
+			if ( getRigWithSceneParity() )
+			{	
+				JointMap :: const_iterator masterJointIt = mJointMap.begin();
+				JointMap :: const_iterator masterJointItEnd = mJointMap.end();
+				for (;masterJointIt!=masterJointItEnd;++masterJointIt )
+				{
+					std::string lookingForJoint = (*masterJointIt).first.c_str();
+
+					if ( mJointList.find( lookingForJoint ) != mJointList.end() )
+					{
+						//LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL;
+						LLMatrix4 jointTransform = mJointList[lookingForJoint];
+						LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData);
+						if ( pJoint )
+						{   
+							LLUUID fake_mesh_id;
+							fake_mesh_id.generate();
+							pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, "");
+						}
+						else
+						{
+							//Most likely an error in the asset.
+							LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL;
+						}
+					}
+				}
+			}
+		} //missingSkeletonOrScene
+
+		//We need to construct the alternate bind matrix (which contains the new joint positions)
+		//in the same order as they were stored in the joint buffer. The joints associated
+		//with the skeleton are not stored in the same order as they are in the exported joint buffer.
+		//This remaps the skeletal joints to be in the same order as the joints stored in the model.
+		std::vector<std::string> :: const_iterator jointIt  = model->mSkinInfo.mJointNames.begin();
+		const int jointCnt = model->mSkinInfo.mJointNames.size();
+		for ( int i=0; i<jointCnt; ++i, ++jointIt )
+		{
+			std::string lookingForJoint = (*jointIt).c_str();
+			//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
+			//and store it in the alternate bind matrix
+			if ( mJointList.find( lookingForJoint ) != mJointList.end() )
+			{
+				LLMatrix4 jointTransform = mJointList[lookingForJoint];
+				LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
+				newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
+				model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
+			}
+			else
+			{
+				LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL;
+			}
+		}
+
+		//grab raw position array
+
+		domVertices* verts = mesh->getVertices();
+		if (verts)
+		{
+			domInputLocal_Array& inputs = verts->getInput_array();
+			for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i)
+			{
+				if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0)
+				{
+					domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
+					if (pos_source)
+					{
+						domFloat_array* pos_array = pos_source->getFloat_array();
+						if (pos_array)
+						{
+							domListOfFloats& pos = pos_array->getValue();
+
+							for (size_t j = 0; j < pos.getCount(); j += 3)
+							{
+								if (pos.getCount() <= j+2)
+								{
+									LL_ERRS() << "Invalid position array size." << LL_ENDL;
+								}
+
+								LLVector3 v(pos[j], pos[j+1], pos[j+2]);
+
+								//transform from COLLADA space to volume space
+								v = v * inverse_normalized_transformation;
+
+								model->mPosition.push_back(v);
+							}
+						}
+					}
+				}
+			}
+		}
+
+		//grab skin weights array
+		domSkin::domVertex_weights* weights = skin->getVertex_weights();
+		if (weights)
+		{
+			domInputLocalOffset_Array& inputs = weights->getInput_array();
+			domFloat_array* vertex_weights = NULL;
+			for (size_t i = 0; i < inputs.getCount(); ++i)
+			{
+				if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0)
+				{
+					domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
+					if (weight_source)
+					{
+						vertex_weights = weight_source->getFloat_array();
+					}
+				}
+			}
+
+			if (vertex_weights)
+			{
+				domListOfFloats& w = vertex_weights->getValue();
+				domListOfUInts& vcount = weights->getVcount()->getValue();
+				domListOfInts& v = weights->getV()->getValue();
+
+				U32 c_idx = 0;
+				for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx)
+				{ //for each vertex
+					daeUInt count = vcount[vc_idx];
+
+					//create list of weights that influence this vertex
+					LLModel::weight_list weight_list;
+
+					for (daeUInt i = 0; i < count; ++i)
+					{ //for each weight
+						daeInt joint_idx = v[c_idx++];
+						daeInt weight_idx = v[c_idx++];
+
+						if (joint_idx == -1)
+						{
+							//ignore bindings to bind_shape_matrix
+							continue;
+						}
+
+						F32 weight_value = w[weight_idx];
+
+						weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value));
+					}
+
+					//sort by joint weight
+					std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater());
+
+					std::vector<LLModel::JointWeight> wght;
+
+					F32 total = 0.f;
+
+					for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i)
+					{ //take up to 4 most significant weights
+						if (weight_list[i].mWeight > 0.f)
+						{
+							wght.push_back( weight_list[i] );
+							total += weight_list[i].mWeight;
+						}
+					}
+
+					F32 scale = 1.f/total;
+					if (scale != 1.f)
+					{ //normalize weights
+						for (U32 i = 0; i < wght.size(); ++i)
+						{
+							wght[i].mWeight *= scale;
+						}
+					}
+
+					model->mSkinWeights[model->mPosition[vc_idx]] = wght;
+				}
+			}
+
+		}
+
+		//add instance to scene for this model
+
+		LLMatrix4 transformation;
+		transformation.initScale(mesh_scale_vector);
+		transformation.setTranslation(mesh_translation_vector);
+		transformation *= mTransform;
+
+		std::map<std::string, LLImportMaterial> materials;
+		for (U32 i = 0; i < model->mMaterialList.size(); ++i)
+		{
+			materials[model->mMaterialList[i]] = LLImportMaterial();
+		}
+		mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
+		stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
+	}
+}
+
+//-----------------------------------------------------------------------------
+// buildJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLDAELoader::buildJointToNodeMappingFromScene( daeElement* pRoot )
+{
+	daeElement* pScene = pRoot->getDescendant("visual_scene");
+	if ( pScene )
+	{
+		daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
+		S32 childCount = children.getCount();
+		for (S32 i = 0; i < childCount; ++i)
+		{
+			domNode* pNode = daeSafeCast<domNode>(children[i]);
+			processJointToNodeMapping( pNode );			
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// processJointToNodeMapping()
+//-----------------------------------------------------------------------------
+void LLDAELoader::processJointToNodeMapping( domNode* pNode )
+{
+	if ( isNodeAJoint( pNode ) )
+	{
+		//1.Store the parent
+		std::string nodeName = pNode->getName();
+		if ( !nodeName.empty() )
+		{
+			mJointsFromNode.push_front( pNode->getName() );
+		}
+		//2. Handle the kiddo's
+		processChildJoints( pNode );
+	}
+	else
+	{
+		//Determine if the're any children wrt to this failed node.
+		//This occurs when an armature is exported and ends up being what essentially amounts to
+		//as the root for the visual_scene
+		if ( pNode ) 
+		{
+			processChildJoints( pNode );
+		}
+		else 
+		{
+			LL_INFOS()<<"Node is NULL"<<LL_ENDL;
+		}
+
+	}
+}
+//-----------------------------------------------------------------------------
+// processChildJoint()
+//-----------------------------------------------------------------------------
+void LLDAELoader::processChildJoints( domNode* pParentNode )
+{	
+	daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren();
+	S32 childOfChildCount = childOfChild.getCount();
+	for (S32 i = 0; i < childOfChildCount; ++i)
+	{
+		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+		if ( pChildNode )
+		{
+			processJointToNodeMapping( pChildNode );
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+// isNodeAJoint()
+//-----------------------------------------------------------------------------
+bool LLDAELoader::isNodeAJoint( domNode* pNode )
+{
+	if ( !pNode )
+	{
+		LL_INFOS()<<"Created node is NULL"<<LL_ENDL;
+		return false;
+	}
+	
+	return LLModelLoader::isNodeAJoint(pNode->getName());
+}
+//-----------------------------------------------------------------------------
+// verifyCount
+//-----------------------------------------------------------------------------
+bool LLDAELoader::verifyCount( int expected, int result )
+{
+	if ( expected != result )
+	{
+		LL_INFOS()<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<LL_ENDL;
+		return false;
+	}
+	return true;
+}
+//-----------------------------------------------------------------------------
+// verifyController
+//-----------------------------------------------------------------------------
+bool LLDAELoader::verifyController( domController* pController )
+{	
+
+	bool result = true;
+
+	domSkin* pSkin = pController->getSkin();
+
+	if ( pSkin )
+	{
+		xsAnyURI & uri = pSkin->getSource();
+		domElement* pElement = uri.getElement();
+
+		if ( !pElement )
+		{
+			LL_INFOS()<<"Can't resolve skin source"<<LL_ENDL;
+			return false;
+		}
+
+		daeString type_str = pElement->getTypeName();
+		if ( stricmp(type_str, "geometry") == 0 )
+		{	
+			//Skin is reference directly by geometry and get the vertex count from skin
+			domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
+			U32 vertexWeightsCount = pVertexWeights->getCount();
+			domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
+			domMesh* pMesh = pGeometry->getMesh();				
+			
+			if ( pMesh )
+			{
+				//Get vertex count from geometry
+				domVertices* pVertices = pMesh->getVertices();
+				if ( !pVertices )
+				{ 
+					LL_INFOS()<<"No vertices!"<<LL_ENDL;
+					return false;
+				}
+
+				if ( pVertices )
+				{
+					xsAnyURI src = pVertices->getInput_array()[0]->getSource();
+					domSource* pSource = (domSource*) (domElement*) src.getElement();
+					U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
+					result = verifyCount( verticesCount, vertexWeightsCount );
+					if ( !result )
+					{
+						return result;
+					}
+				}
+			}	
+
+			U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
+			result = verifyCount( vcountCount, vertexWeightsCount );	
+			if ( !result )
+			{
+				return result;
+			}
+
+			domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
+			U32 sum = 0;
+			for (size_t i=0; i<vcountCount; i++)
+			{
+				sum += pVertexWeights->getVcount()->getValue()[i];
+			}
+			result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
+		}
+	}
+	
+	return result;
+}
+
+//-----------------------------------------------------------------------------
+// extractTranslation()
+//-----------------------------------------------------------------------------
+void LLDAELoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform )
+{
+	domFloat3 jointTrans = pTranslate->getValue();
+	LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
+	transform.setTranslation( singleJointTranslation );
+}
+//-----------------------------------------------------------------------------
+// extractTranslationViaElement()
+//-----------------------------------------------------------------------------
+void LLDAELoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
+{
+	if ( pTranslateElement )
+	{
+		domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
+		domFloat3 translateChild = pTranslateChild->getValue();
+		LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
+		transform.setTranslation( singleJointTranslation );
+	}	
+}
+//-----------------------------------------------------------------------------
+// extractTranslationViaSID()
+//-----------------------------------------------------------------------------
+void LLDAELoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform )
+{
+	if ( pElement )
+	{	
+		daeSIDResolver resolver( pElement, "./transform" );
+		domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() );
+		//We are only extracting out the translational component atm
+		LLMatrix4 workingTransform;
+		if ( pMatrix )
+		{
+			domFloat4x4 domArray = pMatrix->getValue();									
+			for ( int i = 0; i < 4; i++ )
+			{
+				for( int j = 0; j < 4; j++ )
+				{
+					workingTransform.mMatrix[i][j] = domArray[i + j*4];
+				}
+			}
+			LLVector3 trans = workingTransform.getTranslation();
+			transform.setTranslation( trans );	
+		}
+	}
+	else
+	{
+		LL_WARNS()<<"Element is nonexistent - empty/unsupported node."<<LL_ENDL;
+	}
+}
+//-----------------------------------------------------------------------------
+// processJointNode()
+//-----------------------------------------------------------------------------
+void LLDAELoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms )
+{
+	if (pNode->getName() == NULL)
+	{
+		LL_WARNS() << "nameless node, can't process" << LL_ENDL;
+		return;
+	}
+
+	//LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL;
+
+	//1. handle the incoming node - extract out translation via SID or element
+
+	LLMatrix4 workingTransform;
+
+	//Pull out the translate id and store it in the jointTranslations map
+	daeSIDResolver jointResolverA( pNode, "./translate" );
+	domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
+	daeSIDResolver jointResolverB( pNode, "./location" );
+	domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
+
+	//Translation via SID was successful
+	if ( pTranslateA )
+	{
+		extractTranslation( pTranslateA, workingTransform );
+	}
+	else
+	if ( pTranslateB )
+	{
+		extractTranslation( pTranslateB, workingTransform );
+	}
+	else
+	{
+		//Translation via child from element
+		daeElement* pTranslateElement = getChildFromElement( pNode, "translate" );
+		if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() )
+		{
+			//LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
+			daeSIDResolver jointResolver( pNode, "./matrix" );
+			domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() );
+			if ( pMatrix )
+			{
+				//LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL;
+				domFloat4x4 domArray = pMatrix->getValue();									
+				for ( int i = 0; i < 4; i++ )
+				{
+					for( int j = 0; j < 4; j++ )
+					{
+						workingTransform.mMatrix[i][j] = domArray[i + j*4];
+					}
+				}
+			}
+			else
+			{
+				LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL;
+			}
+		}
+		else
+		{
+			extractTranslationViaElement( pTranslateElement, workingTransform );
+		}
+	}
+
+	//Store the working transform relative to the nodes name.
+	jointTransforms[ pNode->getName() ] = workingTransform;
+
+	//2. handle the nodes children
+
+	//Gather and handle the incoming nodes children
+	daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
+	S32 childOfChildCount = childOfChild.getCount();
+
+	for (S32 i = 0; i < childOfChildCount; ++i)
+	{
+		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+		if ( pChildNode )
+		{
+			processJointNode( pChildNode, jointTransforms );
+		}
+	}
+}
+//-----------------------------------------------------------------------------
+// getChildFromElement()
+//-----------------------------------------------------------------------------
+daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string const & name )
+{
+    daeElement* pChildOfElement = pElement->getChild( name.c_str() );
+	if ( pChildOfElement )
+	{
+		return pChildOfElement;
+	}
+	LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
+    return NULL;
+}
+
+void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae )
+{
+	LLMatrix4 saved_transform;
+	bool pushed_mat = false;
+
+	domNode* node = daeSafeCast<domNode>(element);
+	if (node)
+	{
+		pushed_mat = true;
+		saved_transform = mTransform;
+	}
+
+	domTranslate* translate = daeSafeCast<domTranslate>(element);
+	if (translate)
+	{
+		domFloat3 dom_value = translate->getValue();
+
+		LLMatrix4 translation;
+		translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2]));
+
+		translation *= mTransform;
+		mTransform = translation;
+		mTransform.condition();
+	}
+
+	domRotate* rotate = daeSafeCast<domRotate>(element);
+	if (rotate)
+	{
+		domFloat4 dom_value = rotate->getValue();
+
+		LLMatrix4 rotation;
+		rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0));
+
+		rotation *= mTransform;
+		mTransform = rotation;
+		mTransform.condition();
+	}
+
+	domScale* scale = daeSafeCast<domScale>(element);
+	if (scale)
+	{
+		domFloat3 dom_value = scale->getValue();
+
+
+		LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]);
+		scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes
+		LLMatrix4 scaling;
+		scaling.initScale(scale_vector);
+
+		scaling *= mTransform;
+		mTransform = scaling;
+		mTransform.condition();
+	}
+
+	domMatrix* matrix = daeSafeCast<domMatrix>(element);
+	if (matrix)
+	{
+		domFloat4x4 dom_value = matrix->getValue();
+
+		LLMatrix4 matrix_transform;
+
+		for (int i = 0; i < 4; i++)
+		{
+			for(int j = 0; j < 4; j++)
+			{
+				matrix_transform.mMatrix[i][j] = dom_value[i + j*4];
+			}
+		}
+
+		matrix_transform *= mTransform;
+		mTransform = matrix_transform;
+		mTransform.condition();
+	}
+
+	domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element);
+	if (instance_geo)
+	{
+		domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement());
+		if (geo)
+		{
+			domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())));
+			if (mesh)
+			{
+
+				std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();				
+				while (i != mModelsMap[mesh].end())
+				{
+					LLModel* model = *i;
+
+					LLMatrix4 transformation = mTransform;
+				
+					if (mTransform.determinant() < 0)
+					{ //negative scales are not supported
+						LL_INFOS() << "Negative scale detected, unsupported transform.  domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
+						badElement = true;
+					}
+
+					LLModelLoader::material_map materials = getMaterials(model, instance_geo, dae);
+
+					// adjust the transformation to compensate for mesh normalization
+					LLVector3 mesh_scale_vector;
+					LLVector3 mesh_translation_vector;
+					model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
+
+					LLMatrix4 mesh_translation;
+					mesh_translation.setTranslation(mesh_translation_vector);
+					mesh_translation *= transformation;
+					transformation = mesh_translation;
+					
+					LLMatrix4 mesh_scale;
+					mesh_scale.initScale(mesh_scale_vector);
+					mesh_scale *= transformation;
+					transformation = mesh_scale;
+
+					if (transformation.determinant() < 0)
+					{ //negative scales are not supported
+						LL_INFOS() << "Negative scale detected, unsupported post-normalization transform.  domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
+						badElement = true;
+					}
+
+					std::string label;
+					
+					if (model->mLabel.empty())
+					{
+						label = getLodlessLabel(instance_geo);
+
+						llassert(!label.empty());
+
+						if (model->mSubmodelID)
+						{
+							label += (char)((int)'a' + model->mSubmodelID);
+						}
+
+						model->mLabel = label + lod_suffix[mLod];
+					}
+					else
+					{
+						// Don't change model's name if possible, it will play havoc with scenes that already use said model.
+						size_t ext_pos = getSuffixPosition(model->mLabel);
+						if (ext_pos != -1)
+						{
+							label = model->mLabel.substr(0, ext_pos);
+						}
+						else
+						{
+							label = model->mLabel;
+						}
+					}
+
+					mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
+					stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
+					i++;
+				}
+			}
+		}
+		else 
+		{
+			LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL;
+			badElement = true;			
+		}
+
+	}	
+
+	domInstance_node* instance_node = daeSafeCast<domInstance_node>(element);
+	if (instance_node)
+	{
+		daeElement* instance = instance_node->getUrl().getElement();
+		if (instance)
+		{
+			processElement(instance,badElement, dae);
+		}
+	}
+
+	//process children
+	daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
+	int childCount = children.getCount();
+	for (S32 i = 0; i < childCount; i++)
+	{
+		processElement(children[i],badElement, dae);
+	}
+
+	if (pushed_mat)
+	{ //this element was a node, restore transform before processiing siblings
+		mTransform = saved_transform;
+	}
+}
+
+std::map<std::string, LLImportMaterial> LLDAELoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae)
+{
+	std::map<std::string, LLImportMaterial> materials;
+	for (int i = 0; i < model->mMaterialList.size(); i++)
+	{
+		LLImportMaterial import_material;
+
+		domInstance_material* instance_mat = NULL;
+
+		domBind_material::domTechnique_common* technique =
+		daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID())));
+
+		if (technique)
+		{
+			daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>();
+			for (int j = 0; j < inst_materials.getCount(); j++)
+			{
+				std::string symbol(inst_materials[j]->getSymbol());
+
+				if (symbol == model->mMaterialList[i]) // found the binding
+				{
+					instance_mat = inst_materials[j];
+					break;
+				}
+			}
+		}
+
+		if (instance_mat)
+		{
+			domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement());
+			if (material)
+			{
+				domInstance_effect* instance_effect =
+				daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID())));
+				if (instance_effect)
+				{
+					domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement());
+					if (effect)
+					{
+						domProfile_COMMON* profile =
+						daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID())));
+						if (profile)
+						{
+							import_material = profileToMaterial(profile, dae);
+						}
+					}
+				}
+			}
+		}
+
+		import_material.mBinding = model->mMaterialList[i];
+		materials[model->mMaterialList[i]] = import_material;
+	}
+
+	return materials;
+}
+
+LLImportMaterial LLDAELoader::profileToMaterial(domProfile_COMMON* material, DAE* dae)
+{
+	LLImportMaterial mat;
+	mat.mFullbright = FALSE;
+
+	daeElement* diffuse = material->getDescendant("diffuse");
+	if (diffuse)
+	{
+		domCommon_color_or_texture_type_complexType::domTexture* texture =
+		daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture"));
+		if (texture)
+		{
+			domCommon_newparam_type_Array newparams = material->getNewparam_array();
+			if (newparams.getCount())
+			{
+
+				for (S32 i = 0; i < newparams.getCount(); i++)
+				{
+					domFx_surface_common* surface = newparams[i]->getSurface();
+					if (surface)
+					{
+						domFx_surface_init_common* init = surface->getFx_surface_init_common();
+						if (init)
+						{
+							domFx_surface_init_from_common_Array init_from = init->getInit_from_array();
+
+							if (init_from.getCount() > i)
+							{
+								domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement());
+								if (image)
+								{
+									// we only support init_from now - embedded data will come later
+									domImage::domInit_from* init = image->getInit_from();
+									if (init)
+									{									
+										mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str());
+										mat.mDiffuseMapLabel = getElementLabel(material);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			else if (texture->getTexture())
+			{
+				domImage* image = NULL;
+				dae->getDatabase()->getElement((daeElement**) &image, 0, texture->getTexture(), COLLADA_TYPE_IMAGE);
+				if (image)
+				{
+					// we only support init_from now - embedded data will come later
+					domImage::domInit_from* init = image->getInit_from();
+					if (init)
+					{
+						std::string image_path_value = cdom::uriToNativePath(init->getValue().str());
+
+#if LL_WINDOWS
+						// Work-around DOM tendency to resort to UNC names which are only confusing for downstream...
+						//
+						std::string::iterator i = image_path_value.begin();
+						while (*i == '\\')
+							i++;
+						mat.mDiffuseMapFilename.assign(i, image_path_value.end());
+#else
+						mat.mDiffuseMapFilename = image_path_value;
+#endif
+						mat.mDiffuseMapLabel = getElementLabel(material);
+					}
+				}
+			}
+		}
+
+		domCommon_color_or_texture_type_complexType::domColor* color =
+		daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color"));
+		if (color)
+		{
+			domFx_color_common domfx_color = color->getValue();
+			LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
+			mat.mDiffuseColor = value;
+		}
+	}
+
+	daeElement* emission = material->getDescendant("emission");
+	if (emission)
+	{
+		LLColor4 emission_color = getDaeColor(emission);
+		if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25)
+		{
+			mat.mFullbright = TRUE;
+		}
+	}
+
+	return mat;
+}
+
+// try to get a decent label for this element
+std::string LLDAELoader::getElementLabel(daeElement *element)
+{
+	// if we have a name attribute, use it
+	std::string name = element->getAttribute("name");
+	if (name.length())
+	{
+		return name;
+	}
+
+	// if we have an ID attribute, use it
+	if (element->getID())
+	{
+		return std::string(element->getID());
+	}
+
+	// if we have a parent, use it
+	daeElement* parent = element->getParent();
+	std::string index_string;
+	if (parent)
+	{
+		// retrieve index to distinguish items inside same parent
+		size_t ind = 0;
+		parent->getChildren().find(element, ind);
+		index_string = "_" + boost::lexical_cast<std::string>(ind);
+
+		// if parent has a name or ID, use it
+		std::string name = parent->getAttribute("name");
+		if (!name.length())
+		{
+			name = std::string(parent->getID());
+		}
+
+		if (name.length())
+		{
+			// make sure that index won't mix up with pre-named lod extensions
+			size_t ext_pos = getSuffixPosition(name);
+
+			if (ext_pos == -1)
+			{
+				return name + index_string;
+			}
+			else
+			{
+				return name.insert(ext_pos, index_string);
+			}
+		}
+	}
+
+	// try to use our type
+	daeString element_name = element->getElementName();
+	if (element_name)
+	{
+		return std::string(element_name) + index_string;
+	}
+
+	// if all else fails, use "object"
+	return std::string("object") + index_string;
+}
+
+// static
+size_t LLDAELoader::getSuffixPosition(std::string label)
+{
+	if ((label.find("_LOD") != -1) || (label.find("_PHYS") != -1))
+	{
+		return label.rfind('_');
+	}
+	return -1;
+}
+
+// static
+std::string LLDAELoader::getLodlessLabel(daeElement *element)
+{
+	std::string label = getElementLabel(element);
+	size_t ext_pos = getSuffixPosition(label);
+	if (ext_pos != -1)
+	{
+		return label.substr(0, ext_pos);
+	}
+	return label;
+}
+
+LLColor4 LLDAELoader::getDaeColor(daeElement* element)
+{
+	LLColor4 value;
+	domCommon_color_or_texture_type_complexType::domColor* color =
+	daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color"));
+	if (color)
+	{
+		domFx_color_common domfx_color = color->getValue();
+		value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
+	}
+
+	return value;
+}
+
+bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh)
+{
+	LLModel::EModelStatus status = LLModel::NO_ERRORS;
+	domTriangles_Array& tris = mesh->getTriangles_array();
+
+	for (U32 i = 0; i < tris.getCount(); ++i)
+	{
+		domTrianglesRef& tri = tris.get(i);
+
+		status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri);
+		pModel->mStatus = status;
+		if(status != LLModel::NO_ERRORS)
+		{
+			pModel->ClearFacesAndMaterials();
+			return false;
+		}
+	}
+
+	domPolylist_Array& polys = mesh->getPolylist_array();
+	for (U32 i = 0; i < polys.getCount(); ++i)
+	{
+		domPolylistRef& poly = polys.get(i);
+		status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly);
+
+		if(status != LLModel::NO_ERRORS)
+		{
+			pModel->ClearFacesAndMaterials();
+			return false;
+		}
+	}
+
+	domPolygons_Array& polygons = mesh->getPolygons_array();
+
+	for (U32 i = 0; i < polygons.getCount(); ++i)
+	{
+		domPolygonsRef& poly = polygons.get(i);
+		status = load_face_from_dom_polygons(pModel->getVolumeFaces(), pModel->getMaterialList(), poly);
+
+		if(status != LLModel::NO_ERRORS)
+		{
+			pModel->ClearFacesAndMaterials();
+			return false;
+		}
+	}
+
+	return (status == LLModel::NO_ERRORS);
+}
+
+//static 
+LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
+{
+	LLVolumeParams volume_params;
+	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+	LLModel* ret = new LLModel(volume_params, 0.f); 
+	createVolumeFacesFromDomMesh(ret, mesh);
+    if (ret->mLabel.empty())
+    {
+	    ret->mLabel = getElementLabel(mesh);
+    }
+    return ret;
+}
+
+//static diff version supports creating multiple models when material counts spill
+// over the 8 face server-side limit
+//
+bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit)
+{
+
+	LLVolumeParams volume_params;
+	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+	models_out.clear();
+
+	LLModel* ret = new LLModel(volume_params, 0.f);
+
+	std::string model_name = getLodlessLabel(mesh);
+	ret->mLabel = model_name + lod_suffix[mLod];
+
+	llassert(!ret->mLabel.empty());
+
+	// Like a monkey, ready to be shot into space
+	//
+	ret->ClearFacesAndMaterials();
+
+	// Get the whole set of volume faces
+	//
+	addVolumeFacesFromDomMesh(ret, mesh);
+
+	U32 volume_faces = ret->getNumVolumeFaces();
+
+	// Side-steps all manner of issues when splitting models
+	// and matching lower LOD materials to base models
+	//
+	ret->sortVolumeFacesByMaterialName();
+
+	bool normalized = false;
+
+    int submodelID = 0;
+
+	// remove all faces that definitely won't fit into one model and submodel limit
+	U32 face_limit = (submodel_limit + 1) * LL_SCULPT_MESH_MAX_FACES;
+	if (face_limit < volume_faces)
+	{
+		ret->setNumVolumeFaces(face_limit);
+	}
+
+	LLVolume::face_list_t remainder;
+	do 
+	{
+		// Insure we do this once with the whole gang and not per-model
+		//
+		if (!normalized && !mNoNormalize)
+		{			
+			normalized = true;
+			ret->normalizeVolumeFaces();
+		}
+
+		ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
+
+		if (!mNoOptimize)
+		{
+			ret->optimizeVolumeFaces();
+		}
+
+		volume_faces = remainder.size();
+
+		models_out.push_back(ret);
+
+		// If we have left-over volume faces, create another model
+		// to absorb them...
+		//
+		if (volume_faces)
+		{
+			LLModel* next = new LLModel(volume_params, 0.f);
+			next->mSubmodelID = ++submodelID;
+			next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod];
+			next->getVolumeFaces() = remainder;
+			next->mNormalizedScale = ret->mNormalizedScale;
+			next->mNormalizedTranslation = ret->mNormalizedTranslation;
+			if ( ret->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES)
+			{
+				next->mMaterialList.assign(ret->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, ret->mMaterialList.end());
+			}
+			ret = next;
+		}
+
+		remainder.clear();
+
+	} while (volume_faces);	
+
+	return true;
+}
+
+bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
+{
+	if (mesh)
+	{
+		pModel->ClearFacesAndMaterials();
+
+		addVolumeFacesFromDomMesh(pModel, mesh);
+
+		if (pModel->getNumVolumeFaces() > 0)
+		{
+			pModel->normalizeVolumeFaces();
+			pModel->optimizeVolumeFaces();
+
+			if (pModel->getNumVolumeFaces() > 0)
+			{
+				return true;
+			}
+		}
+	}
+	else
+	{	
+		LL_WARNS() << "no mesh found" << LL_ENDL;
+	}
+
+	return false;
+}
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d91a6063b4cad0e4a2ed78443ce288012f3ee3d
--- /dev/null
+++ b/indra/llprimitive/lldaeloader.h
@@ -0,0 +1,107 @@
+/**
+ * @file lldaeloader.h
+ * @brief LLDAELoader class definition
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDAELOADER_H
+#define LL_LLDAELOADER_H
+
+#include "llmodelloader.h"
+
+class DAE;
+class daeElement;
+class domProfile_COMMON;
+class domInstance_geometry;
+class domNode;
+class domTranslate;
+class domController;
+class domSkin;
+class domMesh;
+
+class LLDAELoader : public LLModelLoader
+{
+public:
+	typedef std::map<std::string, LLImportMaterial>							material_map;
+	typedef std::map<daeElement*, std::vector<LLPointer<LLModel> > >	dae_model_map;
+	dae_model_map	mModelsMap;
+
+	LLDAELoader(
+		std::string									filename,
+		S32											lod, 
+		LLModelLoader::load_callback_t		load_cb,
+		LLModelLoader::joint_lookup_func_t	joint_lookup_func,
+		LLModelLoader::texture_load_func_t	texture_load_func,
+		LLModelLoader::state_callback_t		state_cb,
+		void*											opaque_userdata,
+		JointTransformMap&						jointMap,
+		JointSet&									jointsFromNodes,
+		U32									modelLimit);
+	virtual ~LLDAELoader() ;
+
+	virtual bool OpenFile(const std::string& filename);
+
+protected:
+
+	void processElement(daeElement* element, bool& badElement, DAE* dae);
+	void processDomModel(LLModel* model, DAE* dae, daeElement* pRoot, domMesh* mesh, domSkin* skin);
+
+	material_map getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae);
+	LLImportMaterial profileToMaterial(domProfile_COMMON* material, DAE* dae);	
+	LLColor4 getDaeColor(daeElement* element);
+	
+	daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
+	
+	bool isNodeAJoint( domNode* pNode );
+	void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
+	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
+	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
+	void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform );
+	void buildJointToNodeMappingFromScene( daeElement* pRoot );
+	void processJointToNodeMapping( domNode* pNode );
+	void processChildJoints( domNode* pParentNode );
+
+	bool verifyCount( int expected, int result );
+
+	//Verify that a controller matches vertex counts
+	bool verifyController( domController* pController );
+
+	static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh);
+	static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
+
+	static LLModel* loadModelFromDomMesh(domMesh* mesh);
+
+	// Loads a mesh breaking it into one or more models as necessary
+	// to get around volume face limitations while retaining >8 materials
+	//
+	bool loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit);
+
+	static std::string getElementLabel(daeElement *element);
+	static size_t getSuffixPosition(std::string label);
+	static std::string getLodlessLabel(daeElement *element);
+
+private:
+	U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
+
+};
+#endif  // LL_LLDAELLOADER_H
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index ed903146ef3352887d0886451df58f04877af99d..e494c55250145c74704fbc35690bb67b465c78e4 100755
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -31,867 +31,38 @@
 #include "llconvexdecomposition.h"
 #include "llsdserialize.h"
 #include "llvector4a.h"
-#if LL_MSVC
-#pragma warning (disable : 4263)
-#pragma warning (disable : 4264)
-#endif
-#include "dae.h"
-#include "dae/daeErrorHandler.h"
-#include "dom/domConstants.h"
-#include "dom/domMesh.h"
-#if LL_MSVC
-#pragma warning (default : 4263)
-#pragma warning (default : 4264)
-#endif
-
-#ifdef LL_USESYSTEMLIBS
-# include <zlib.h>
-#else
-# include "zlib/zlib.h"
-#endif
-
-
-
-std::string model_names[] =
-{
-	"lowest_lod",
-	"low_lod",
-	"medium_lod",
-	"high_lod",
-	"physics_mesh"
-};
-
-const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
-
-LLModel::LLModel(LLVolumeParams& params, F32 detail)
-	: LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0)
-	, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS)
-{
-	mDecompID = -1;
-	mLocalID = -1;
-}
-
-LLModel::~LLModel()
-{
-	if (mDecompID >= 0)
-	{
-		LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
-	}
-}
-
-
-bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
-					 domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
-{
-	idx_stride = 0;
-
-	for (U32 j = 0; j < inputs.getCount(); ++j)
-	{
-		idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride);
-
-		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
-		{ //found vertex array
-			const domURIFragmentType& uri = inputs[j]->getSource();
-			daeElementRef elem = uri.getElement();
-			domVertices* vertices = (domVertices*) elem.cast();
-			if ( !vertices )
-			{
-				return false;
-			}
-				
-			domInputLocal_Array& v_inp = vertices->getInput_array();
-			
-			
-			for (U32 k = 0; k < v_inp.getCount(); ++k)
-			{
-				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
-				{
-					pos_offset = inputs[j]->getOffset();
-
-					const domURIFragmentType& uri = v_inp[k]->getSource();
-					daeElementRef elem = uri.getElement();
-					pos_source = (domSource*) elem.cast();
-				}
-				
-				if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0)
-				{
-					norm_offset = inputs[j]->getOffset();
-
-					const domURIFragmentType& uri = v_inp[k]->getSource();
-					daeElementRef elem = uri.getElement();
-					norm_source = (domSource*) elem.cast();
-				}
-			}
-		}
-
-		if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
-		{
-			//found normal array for this triangle list
-			norm_offset = inputs[j]->getOffset();
-			const domURIFragmentType& uri = inputs[j]->getSource();
-			daeElementRef elem = uri.getElement();
-			norm_source = (domSource*) elem.cast();
-		}
-		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
-		{ //found texCoords
-			tc_offset = inputs[j]->getOffset();
-			const domURIFragmentType& uri = inputs[j]->getSource();
-			daeElementRef elem = uri.getElement();
-			tc_source = (domSource*) elem.cast();
-		}
-	}
-
-	idx_stride += 1;
-	
-	return true;
-}
-
-LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
-{
-	LLVolumeFace face;
-	std::vector<LLVolumeFace::VertexData> verts;
-	std::vector<U16> indices;
-	
-	const domInputLocalOffset_Array& inputs = tri->getInput_array();
-
-	S32 pos_offset = -1;
-	S32 tc_offset = -1;
-	S32 norm_offset = -1;
-
-	domSource* pos_source = NULL;
-	domSource* tc_source = NULL;
-	domSource* norm_source = NULL;
-
-	S32 idx_stride = 0;
-
-	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
-	{
-		LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL;
-		return LLModel::BAD_ELEMENT;
-	}
-
-	if (!pos_source)
-	{
-		LL_WARNS() << "Unable to process mesh without position data; invalid model;  invalid model." << LL_ENDL;
-		return LLModel::BAD_ELEMENT;
-	}
-	
-	domPRef p = tri->getP();
-	domListOfUInts& idx = p->getValue();
-	
-	domListOfFloats  dummy ;
-	domListOfFloats& v = (pos_source && pos_source->getFloat_array()) ? pos_source->getFloat_array()->getValue() : dummy ;
-	domListOfFloats& tc = (tc_source && tc_source->getFloat_array()) ? tc_source->getFloat_array()->getValue() : dummy ;
-	domListOfFloats& n = (norm_source && norm_source->getFloat_array()) ? norm_source->getFloat_array()->getValue() : dummy ;
-
-	LLVolumeFace::VertexMapData::PointMap point_map;
-		
-	U32 index_count  = idx.getCount();
-	U32 vertex_count = (pos_source &&  pos_source->getFloat_array())	? v.getCount()	: 0;
-	U32 tc_count     = (tc_source && tc_source->getFloat_array()) 		? tc.getCount()	: 0;
-	U32 norm_count   = (norm_source && norm_source->getFloat_array()) 	? n.getCount(): 0;
-
-	if (vertex_count == 0)
-	{
-		LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL;
-		return LLModel::BAD_ELEMENT;
-	}
-
-	face.mExtents[0].set(v[0], v[1], v[2]);
-	face.mExtents[1].set(v[0], v[1], v[2]);
-	
-	for (U32 i = 0; i < index_count; i += idx_stride)
-	{
-		LLVolumeFace::VertexData cv;
-		if (pos_source)
-		{
-			// guard against model data specifiying out of range indices or verts
-			//
-			if (((i + pos_offset) > index_count)
-			 || ((idx[i+pos_offset]*3+2) > vertex_count))
-			{
-				LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-
-			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
-								v[idx[i+pos_offset]*3+1],
-								v[idx[i+pos_offset]*3+2]));
-
-			if (!cv.getPosition().isFinite3())
-			{
-				LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-		}
-
-		if (tc_source)
-		{
-			// guard against model data specifiying out of range indices or tcs
-			//
-
-			if (((i + tc_offset) > index_count)
-			 || ((idx[i+tc_offset]*2+1) > tc_count))
-			{
-				LL_WARNS() << "Out of range TC indices." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-
-			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
-								tc[idx[i+tc_offset]*2+1]);
-
-			if (!cv.mTexCoord.isFinite())
-			{
-				LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-		}
-		
-		if (norm_source)
-		{
-			// guard against model data specifiying out of range indices or norms
-			//
-			if (((i + norm_offset) > index_count)
-				|| ((idx[i+norm_offset]*3+2) > norm_count))
-			{
-				LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-
-			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
-								n[idx[i+norm_offset]*3+1],
-								n[idx[i+norm_offset]*3+2]));
-
-			if (!cv.getNormal().isFinite3())
-			{
-				LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-		}
-		
-		BOOL found = FALSE;
-			
-		LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
-		point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
-		
-		if (point_iter != point_map.end())
-		{
-			for (U32 j = 0; j < point_iter->second.size(); ++j)
-			{
-				if ((point_iter->second)[j] == cv)
-				{
-					found = TRUE;
-					indices.push_back((point_iter->second)[j].mIndex);
-					break;
-				}
-			}
-		}
-
-		if (!found)
-		{
-			update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
-			verts.push_back(cv);
-			if (verts.size() >= 65535)
-			{
-				//LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
-				return LLModel::VERTEX_NUMBER_OVERFLOW ;
-			}
-			U16 index = (U16) (verts.size()-1);
-			indices.push_back(index);
-
-			LLVolumeFace::VertexMapData d;
-			d.setPosition(cv.getPosition());
-			d.mTexCoord = cv.mTexCoord;
-			d.setNormal(cv.getNormal());
-			d.mIndex = index;
-			if (point_iter != point_map.end())
-			{
-				point_iter->second.push_back(d);
-			}
-			else
-			{
-				point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
-			}
-		}
-
-		if (indices.size()%3 == 0 && verts.size() >= 65532)
-		{
-			std::string material;
-
-			if (tri->getMaterial())
-			{
-				material = std::string(tri->getMaterial());
-			}
-
-			materials.push_back(material);
-			face_list.push_back(face);
-			face_list.rbegin()->fillFromLegacyData(verts, indices);
-			LLVolumeFace& new_face = *face_list.rbegin();
-			if (!norm_source)
-			{
-				//ll_aligned_free_16(new_face.mNormals);
-				new_face.mNormals = NULL;
-			}
-
-			if (!tc_source)
-			{
-				//ll_aligned_free_16(new_face.mTexCoords);
-				new_face.mTexCoords = NULL;
-			}
-
-			face = LLVolumeFace();
-			point_map.clear();
-		}
-	}
-
-	if (!verts.empty())
-	{
-		std::string material;
-
-		if (tri->getMaterial())
-		{
-			material = std::string(tri->getMaterial());
-		}
-		
-		materials.push_back(material);
-		face_list.push_back(face);
-
-		face_list.rbegin()->fillFromLegacyData(verts, indices);
-		LLVolumeFace& new_face = *face_list.rbegin();
-		if (!norm_source)
-		{
-			//ll_aligned_free_16(new_face.mNormals);
-			new_face.mNormals = NULL;
-		}
-
-		if (!tc_source)
-		{
-			//ll_aligned_free_16(new_face.mTexCoords);
-			new_face.mTexCoords = NULL;
-		}
-	}
-
-	return LLModel::NO_ERRORS ;
-}
-
-LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly)
-{
-	domPRef p = poly->getP();
-	domListOfUInts& idx = p->getValue();
-
-	if (idx.getCount() == 0)
-	{
-		return LLModel::NO_ERRORS ;
-	}
-
-	const domInputLocalOffset_Array& inputs = poly->getInput_array();
-
-
-	domListOfUInts& vcount = poly->getVcount()->getValue();
-	
-	S32 pos_offset = -1;
-	S32 tc_offset = -1;
-	S32 norm_offset = -1;
-
-	domSource* pos_source = NULL;
-	domSource* tc_source = NULL;
-	domSource* norm_source = NULL;
-
-	S32 idx_stride = 0;
-
-	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
-	{
-		LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL;
-		return LLModel::BAD_ELEMENT;
-	}
-
-	LLVolumeFace face;
-
-	std::vector<U16> indices;
-	std::vector<LLVolumeFace::VertexData> verts;
-
-	domListOfFloats v;
-	domListOfFloats tc;
-	domListOfFloats n;
-
-	if (pos_source)
-	{
-		v = pos_source->getFloat_array()->getValue();
-		face.mExtents[0].set(v[0], v[1], v[2]);
-		face.mExtents[1].set(v[0], v[1], v[2]);
-	}
 
-	if (tc_source)
-	{
-		tc = tc_source->getFloat_array()->getValue();
-	}
-
-	if (norm_source)
-	{
-		n = norm_source->getFloat_array()->getValue();
-	}
-	
-	LLVolumeFace::VertexMapData::PointMap point_map;
-
-	U32 index_count  = idx.getCount();
-	U32 vertex_count = pos_source  ? v.getCount()  : 0;
-	U32 tc_count     = tc_source   ? tc.getCount() : 0;
-	U32 norm_count   = norm_source ? n.getCount()  : 0;
-
-	U32 cur_idx = 0;
-	for (U32 i = 0; i < vcount.getCount(); ++i)
-	{ //for each polygon
-		U32 first_index = 0;
-		U32 last_index = 0;
-		for (U32 j = 0; j < vcount[i]; ++j)
-		{ //for each vertex
-
-			LLVolumeFace::VertexData cv;
-
-			if (pos_source)
-			{
-				// guard against model data specifiying out of range indices or verts
-				//
-				if (((cur_idx + pos_offset) > index_count)
-				 || ((idx[cur_idx+pos_offset]*3+2) > vertex_count))
-				{
-					LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-
-				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
-									v[idx[cur_idx+pos_offset]*3+1],
-									v[idx[cur_idx+pos_offset]*3+2]);
-
-				if (!cv.getPosition().isFinite3())
-				{
-					LL_WARNS() << "Found NaN while loading positions from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-
-			}
-
-			if (tc_source)
-			{
-				// guard against model data specifiying out of range indices or tcs
-				//
-				if (((cur_idx + tc_offset) > index_count)
-				 || ((idx[cur_idx+tc_offset]*2+1) > tc_count))
-				{
-					LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-
-				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
-									tc[idx[cur_idx+tc_offset]*2+1]);
-
-				if (!cv.mTexCoord.isFinite())
-				{
-					LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-			}
-			
-			if (norm_source)
-			{
-				// guard against model data specifiying out of range indices or norms
-				//
-				if (((cur_idx + norm_offset) > index_count)
-				 || ((idx[cur_idx+norm_offset]*3+2) > norm_count))
-				{
-					LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-
-				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
-									n[idx[cur_idx+norm_offset]*3+1],
-									n[idx[cur_idx+norm_offset]*3+2]);
-
-				if (!cv.getNormal().isFinite3())
-				{
-					LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-			}
-			
-			cur_idx += idx_stride;
-			
-			BOOL found = FALSE;
-				
-			LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
-			LLVector3 pos3(cv.getPosition().getF32ptr());
-			point_iter = point_map.find(pos3);
-			
-			if (point_iter != point_map.end())
-			{
-				for (U32 k = 0; k < point_iter->second.size(); ++k)
-				{
-					if ((point_iter->second)[k] == cv)
-					{
-						found = TRUE;
-						U32 index = (point_iter->second)[k].mIndex;
-						if (j == 0)
-						{
-							first_index = index;
-						}
-						else if (j == 1)
-						{
-							last_index = index;
-						}
-						else
-						{
-							indices.push_back(first_index);
-							indices.push_back(last_index);
-							indices.push_back(index);
-							last_index = index;
-						}
-
-						break;
-					}
-				}
-			}
-
-			if (!found)
-			{
-				update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
-				verts.push_back(cv);
-				if (verts.size() >= 65535)
-				{
-					//LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
-					return LLModel::VERTEX_NUMBER_OVERFLOW ;
-				}
-				U16 index = (U16) (verts.size()-1);
-			
-				if (j == 0)
-				{
-					first_index = index;
-				}
-				else if (j == 1)
-				{
-					last_index = index;
-				}
-				else
-				{
-					indices.push_back(first_index);
-					indices.push_back(last_index);
-					indices.push_back(index);
-					last_index = index;
-				}	
-
-				LLVolumeFace::VertexMapData d;
-				d.setPosition(cv.getPosition());
-				d.mTexCoord = cv.mTexCoord;
-				d.setNormal(cv.getNormal());
-				d.mIndex = index;
-				if (point_iter != point_map.end())
-				{
-					point_iter->second.push_back(d);
-				}
-				else
-				{
-					point_map[pos3].push_back(d);
-				}
-			}
-
-			if (indices.size()%3 == 0 && indices.size() >= 65532)
-			{
-				std::string material;
-
-				if (poly->getMaterial())
-				{
-					material = std::string(poly->getMaterial());
-				}
-
-				materials.push_back(material);
-				face_list.push_back(face);
-				face_list.rbegin()->fillFromLegacyData(verts, indices);
-				LLVolumeFace& new_face = *face_list.rbegin();
-				if (!norm_source)
-				{
-					//ll_aligned_free_16(new_face.mNormals);
-					new_face.mNormals = NULL;
-				}
-
-				if (!tc_source)
-				{
-					//ll_aligned_free_16(new_face.mTexCoords);
-					new_face.mTexCoords = NULL;
-				}
-
-				face = LLVolumeFace();
-				verts.clear();
-				indices.clear();
-				point_map.clear();
-			}
-		}
-	}
-
-	if (!verts.empty())
-	{
-		std::string material;
-
-		if (poly->getMaterial())
-		{
-			material = std::string(poly->getMaterial());
-		}
-	
-		materials.push_back(material);
-		face_list.push_back(face);
-		face_list.rbegin()->fillFromLegacyData(verts, indices);
-
-		LLVolumeFace& new_face = *face_list.rbegin();
-		if (!norm_source)
-		{
-			//ll_aligned_free_16(new_face.mNormals);
-			new_face.mNormals = NULL;
-		}
-
-		if (!tc_source)
-		{
-			//ll_aligned_free_16(new_face.mTexCoords);
-			new_face.mTexCoords = NULL;
-		}
-	}
-
-	return LLModel::NO_ERRORS ;
-}
-
-LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly)
-{
-	LLVolumeFace face;
-	std::vector<U16> indices;
-	std::vector<LLVolumeFace::VertexData> verts;
-
-	const domInputLocalOffset_Array& inputs = poly->getInput_array();
-
-	S32 v_offset = -1;
-	S32 n_offset = -1;
-	S32 t_offset = -1;
-
-	domListOfFloats* v = NULL;
-	domListOfFloats* n = NULL;
-	domListOfFloats* t = NULL;
-	
-	U32 stride = 0;
-	for (U32 i = 0; i < inputs.getCount(); ++i)
-	{
-		stride = llmax((U32) inputs[i]->getOffset()+1, stride);
-
-		if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0)
-		{ //found vertex array
-			v_offset = inputs[i]->getOffset();
-
-			const domURIFragmentType& uri = inputs[i]->getSource();
-			daeElementRef elem = uri.getElement();
-			domVertices* vertices = (domVertices*) elem.cast();
-			if (!vertices)
-			{
-				LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-			domInputLocal_Array& v_inp = vertices->getInput_array();
-
-			for (U32 k = 0; k < v_inp.getCount(); ++k)
-			{
-				if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
-				{
-					const domURIFragmentType& uri = v_inp[k]->getSource();
-					daeElementRef elem = uri.getElement();
-					domSource* src = (domSource*) elem.cast();
-					if (!src)
-					{
-						LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL;
-						return LLModel::BAD_ELEMENT;
-					}
-					v = &(src->getFloat_array()->getValue());
-				}
-			}
-		}
-		else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0)
-		{
-			n_offset = inputs[i]->getOffset();
-			//found normal array for this triangle list
-			const domURIFragmentType& uri = inputs[i]->getSource();
-			daeElementRef elem = uri.getElement();
-			domSource* src = (domSource*) elem.cast();
-			if (!src)
-			{
-				LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-			n = &(src->getFloat_array()->getValue());
-		}
-		else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
-		{ //found texCoords
-			t_offset = inputs[i]->getOffset();
-			const domURIFragmentType& uri = inputs[i]->getSource();
-			daeElementRef elem = uri.getElement();
-			domSource* src = (domSource*) elem.cast();
-			if (!src)
-			{
-				LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL;
-				return LLModel::BAD_ELEMENT;
-			}
-			t = &(src->getFloat_array()->getValue());
-		}
-	}
-
-	domP_Array& ps = poly->getP_array();
-
-	//make a triangle list in <verts>
-	for (U32 i = 0; i < ps.getCount(); ++i)
-	{ //for each polygon
-		domListOfUInts& idx = ps[i]->getValue();
-		for (U32 j = 0; j < idx.getCount()/stride; ++j)
-		{ //for each vertex
-			if (j > 2)
-			{
-				U32 size = verts.size();
-				LLVolumeFace::VertexData v0 = verts[size-3];
-				LLVolumeFace::VertexData v1 = verts[size-1];
-
-				verts.push_back(v0);
-				verts.push_back(v1);
-			}
-
-			LLVolumeFace::VertexData vert;
-
-
-			if (v)
-			{
-				U32 v_idx = idx[j*stride+v_offset]*3;
-				v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount());
-				vert.getPosition().set(v->get(v_idx),
-								v->get(v_idx+1),
-								v->get(v_idx+2));
-
-				if (!vert.getPosition().isFinite3())
-				{
-					LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-			}
-			
-			//bounds check n and t lookups because some FBX to DAE converters
-			//use negative indices and empty arrays to indicate data does not exist
-			//for a particular channel
-			if (n && n->getCount() > 0)
-			{
-				U32 n_idx = idx[j*stride+n_offset]*3;
-				n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount());
-				vert.getNormal().set(n->get(n_idx),
-								n->get(n_idx+1),
-								n->get(n_idx+2));
-
-				if (!vert.getNormal().isFinite3())
-				{
-					LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-			}
-			else
-			{
-				vert.getNormal().clear();
-			}
-
-			
-			if (t && t->getCount() > 0)
-			{
-				U32 t_idx = idx[j*stride+t_offset]*2;
-				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
-				vert.mTexCoord.setVec(t->get(t_idx),
-								t->get(t_idx+1));								
-
-				if (!vert.mTexCoord.isFinite())
-				{
-					LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL;
-					return LLModel::BAD_ELEMENT;
-				}
-			}
-			else
-			{
-				vert.mTexCoord.clear();
-			}
-
-						
-			verts.push_back(vert);
-		}
-	}
-
-	if (verts.empty())
-	{
-		return LLModel::NO_ERRORS;
-	}
-
-	face.mExtents[0] = verts[0].getPosition();
-	face.mExtents[1] = verts[0].getPosition();
-	
-	//create a map of unique vertices to indices
-	std::map<LLVolumeFace::VertexData, U32> vert_idx;
-
-	U32 cur_idx = 0;
-	for (U32 i = 0; i < verts.size(); ++i)
-	{
-		std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]);
-		if (iter == vert_idx.end())
-		{
-			vert_idx[verts[i]] = cur_idx++;
-		}
-	}
-
-	//build vertex array from map
-	std::vector<LLVolumeFace::VertexData> new_verts;
-	new_verts.resize(vert_idx.size());
-
-	for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter)
-	{
-		new_verts[iter->second] = iter->first;
-		update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition());
-	}
-
-	//build index array from map
-	indices.resize(verts.size());
-
-	for (U32 i = 0; i < verts.size(); ++i)
-	{
-		indices[i] = vert_idx[verts[i]];
-	}
-
-	// DEBUG just build an expanded triangle list
-	/*for (U32 i = 0; i < verts.size(); ++i)
-	{
-		indices.push_back((U16) i);
-		update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition());
-	}*/
-
-    if (!new_verts.empty())
-	{
-		std::string material;
+#ifdef LL_USESYSTEMLIBS
+# include <zlib.h>
+#else
+# include "zlib/zlib.h"
+#endif
 
-		if (poly->getMaterial())
-		{
-			material = std::string(poly->getMaterial());
-		}
+std::string model_names[] =
+{
+	"lowest_lod",
+	"low_lod",
+	"medium_lod",
+	"high_lod",
+	"physics_mesh"
+};
 
-		materials.push_back(material);
-		face_list.push_back(face);
-		face_list.rbegin()->fillFromLegacyData(new_verts, indices);
+const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
 
-		LLVolumeFace& new_face = *face_list.rbegin();
-		if (!n)
-		{
-			//ll_aligned_free_16(new_face.mNormals);
-			new_face.mNormals = NULL;
-		}
+LLModel::LLModel(LLVolumeParams& params, F32 detail)
+	: LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0)
+	, mPelvisOffset( 0.0f ), mStatus(NO_ERRORS), mSubmodelID(0)
+{
+	mDecompID = -1;
+	mLocalID = -1;
+}
 
-		if (!t)
-		{
-			//ll_aligned_free_16(new_face.mTexCoords);
-			new_face.mTexCoords = NULL;
-		}
+LLModel::~LLModel()
+{
+	if (mDecompID >= 0)
+	{
+		LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
 	}
-
-	return LLModel::NO_ERRORS ;
 }
 
 //static
@@ -903,115 +74,103 @@ std::string LLModel::getStatusString(U32 status)
 	{
 		if(status_strings[status] == std::string())
 		{
-			LL_ERRS() << "No valid status string for this status: " << (U32)status << LL_ENDL ;
+			//LL_ERRS() << "No valid status string for this status: " << (U32)status << LL_ENDL();
 		}
 		return status_strings[status] ;
 	}
 
-	LL_ERRS() << "Invalid model status: " << (U32)status << LL_ENDL ;
+	//LL_ERRS() << "Invalid model status: " << (U32)status << LL_ENDL();
 
 	return std::string() ;
 }
 
-void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
+
+void LLModel::offsetMesh( const LLVector3& pivotPoint )
 {
-	domTriangles_Array& tris = mesh->getTriangles_array();
-		
-	for (U32 i = 0; i < tris.getCount(); ++i)
+	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
+	
+	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )
 	{
-		domTrianglesRef& tri = tris.get(i);
-
-		mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri);
+		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++;
+		LLVolumeFace& face = *currentFaceIt;
+		LLVector4a *pos = (LLVector4a*) face.mPositions;
 		
-		if(mStatus != NO_ERRORS)
+		for (U32 i=0; i<face.mNumVertices; ++i )
 		{
-			mVolumeFaces.clear() ;
-			mMaterialList.clear() ;
-			return ; //abort
+			pos[i].add( pivot );
 		}
 	}
+}
 
-	domPolylist_Array& polys = mesh->getPolylist_array();
-	for (U32 i = 0; i < polys.getCount(); ++i)
-	{
-		domPolylistRef& poly = polys.get(i);
-		mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
-
-		if(mStatus != NO_ERRORS)
-		{
-			mVolumeFaces.clear() ;
-			mMaterialList.clear() ;
-			return ; //abort
-		}
-	}
-	
-	domPolygons_Array& polygons = mesh->getPolygons_array();
-	
-	for (U32 i = 0; i < polygons.getCount(); ++i)
+void LLModel::optimizeVolumeFaces()
+{
+	for (U32 i = 0; i < getNumVolumeFaces(); ++i)
 	{
-		domPolygonsRef& poly = polygons.get(i);
-		mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
-
-		if(mStatus != NO_ERRORS)
-		{
-			mVolumeFaces.clear() ;
-			mMaterialList.clear() ;
-			return ; //abort
-		}
+		mVolumeFaces[i].optimize();
 	}
- 
 }
 
-BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
+struct MaterialBinding
+{
+	int				index;
+	std::string		matName;
+};
+
+struct MaterialSort
 {
-	if (mesh)
+	bool operator()(const MaterialBinding& lhs, const MaterialBinding& rhs)
 	{
-		mVolumeFaces.clear();
-		mMaterialList.clear();
+		return LLStringUtil::compareInsensitive(lhs.matName, rhs.matName) < 0;
+	}
+};
 
-		addVolumeFacesFromDomMesh(mesh);
-		
-		if (getNumVolumeFaces() > 0)
+void LLModel::sortVolumeFacesByMaterialName()
+{
+	std::vector<MaterialBinding> bindings;
+	bindings.resize(mVolumeFaces.size());
+
+	for (int i = 0; i < bindings.size(); i++)
+	{
+		bindings[i].index = i;
+		if(i < mMaterialList.size())
 		{
-			normalizeVolumeFaces();
-			optimizeVolumeFaces();
-			
-			if (getNumVolumeFaces() > 0)
-			{
-				return TRUE;
-			}
+			bindings[i].matName = mMaterialList[i];
 		}
 	}
-	else
-	{	
-		LL_WARNS() << "no mesh found" << LL_ENDL;
-	}
-	
-	return FALSE;
-}
+	std::sort(bindings.begin(), bindings.end(), MaterialSort());
+	std::vector< LLVolumeFace > new_faces;
 
-void LLModel::offsetMesh( const LLVector3& pivotPoint )
-{
-	LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
-	
-	for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )
+	// remap the faces to be in the same order the mats now are...
+	//
+	new_faces.resize(bindings.size());
+	for (int i = 0; i < bindings.size(); i++)
 	{
-		std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++;
-		LLVolumeFace& face = *currentFaceIt;
-		LLVector4a *pos = (LLVector4a*) face.mPositions;
-		
-		for (U32 i=0; i<face.mNumVertices; ++i )
+		new_faces[i] = mVolumeFaces[bindings[i].index];
+		if(i < mMaterialList.size())
 		{
-			pos[i].add( pivot );
+			mMaterialList[i] = bindings[i].matName;
 		}
 	}
+
+	mVolumeFaces = new_faces;	
 }
 
-void LLModel::optimizeVolumeFaces()
+void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remainder)
 {
-	for (U32 i = 0; i < getNumVolumeFaces(); ++i)
+	llassert(new_count <= LL_SCULPT_MESH_MAX_FACES);
+
+	if (new_count && (getNumVolumeFaces() > new_count))
 	{
-		mVolumeFaces[i].optimize();
+		// Copy out remaining volume faces for alternative handling, if provided
+		//
+		if (remainder)
+		{
+			(*remainder).assign(mVolumeFaces.begin() + new_count, mVolumeFaces.end());
+		}		
+
+		// Trim down to the final set of volume faces (now stuffed to the gills!)
+		//
+		mVolumeFaces.resize(new_count);
 	}
 }
 
@@ -1025,11 +184,6 @@ void LLModel::optimizeVolumeFaces()
 // within the unit cube.
 void LLModel::normalizeVolumeFaces()
 {
-
-	// ensure we don't have too many faces
-	if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES)
-		mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES);
-	
 	if (!mVolumeFaces.empty())
 	{
 		LLVector4a min, max;
@@ -1496,68 +650,10 @@ void LLModel::generateNormals(F32 angle_cutoff)
 	}
 }
 
-//static
-std::string LLModel::getElementLabel(daeElement *element)
-{ // try to get a decent label for this element
-	// if we have a name attribute, use it
-	std::string name = element->getAttribute("name");
-	if (name.length())
-	{
-		return name;
-	}
-
-	// if we have an ID attribute, use it
-	if (element->getID())
-	{
-		return std::string(element->getID());
-	}
-
-	// if we have a parent, use it
-	daeElement* parent = element->getParent();
-	if (parent)
-	{
-		// if parent has a name, use it
-		std::string name = parent->getAttribute("name");
-		if (name.length())
-		{
-			return name;
-		}
-
-		// if parent has an ID, use it
-		if (parent->getID())
-		{
-			return std::string(parent->getID());
-		}
-	}
-
-	// try to use our type
-	daeString element_name = element->getElementName();
-	if (element_name)
-	{
-		return std::string(element_name);
-	}
-
-	// if all else fails, use "object"
-	return std::string("object");
-}
-
-//static 
-LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
-{
-	LLVolumeParams volume_params;
-	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
-	LLModel* ret = new LLModel(volume_params, 0.f); 
-	ret->createVolumeFacesFromDomMesh(mesh);
-	ret->mLabel = getElementLabel(mesh);
-	return ret;
-}
 
 std::string LLModel::getName() const
 {
-	if (!mRequestedLabel.empty())
-		return mRequestedLabel;
-	else
-		return mLabel;
+    return mRequestedLabel.empty() ? mLabel : mRequestedLabel;
 }
 
 //static
@@ -1572,7 +668,8 @@ LLSD LLModel::writeModel(
 	BOOL upload_skin,
 	BOOL upload_joints,
 	BOOL nowrite,
-	BOOL as_slm)
+	BOOL as_slm,
+	int submodel_id)
 {
 	LLSD mdl;
 
@@ -1601,6 +698,14 @@ LLSD LLModel::writeModel(
 			model[LLModel::LOD_PHYSICS] = NULL;
 		}
 	}
+	else if (submodel_id)
+	{
+		const LLModel::Decomposition fake_decomp;
+		mdl["secondary"] = true;
+        mdl["submodel_id"] = submodel_id;
+		mdl["physics_convex"] = fake_decomp.asLLSD();
+		model[LLModel::LOD_PHYSICS] = NULL;
+	}
 
 	if (as_slm)
 	{ //save material list names
@@ -1612,7 +717,7 @@ LLSD LLModel::writeModel(
 
 	for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
 	{
-		if (model[idx] && model[idx]->getNumVolumeFaces() > 0)
+		if (model[idx] && (model[idx]->getNumVolumeFaces() > 0) && model[idx]->getVolumeFace(0).mPositions != NULL)
 		{
 			LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr());
 			LLVector3 max_pos = min_pos;
@@ -1845,6 +950,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO
 		}
 	}
 
+        if (mdl.has("submodel_id"))
+        { //write out submodel id
+        header["submodel_id"] = (LLSD::Integer)mdl["submodel_id"];
+        }
+
 	std::string out[MODEL_NAMES_LENGTH];
 
 	for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@@ -2028,7 +1138,9 @@ bool LLModel::loadModel(std::istream& is)
 		}
 	}
 
-	static const std::string nm[] = 
+	mSubmodelID = header.has("submodel_id") ? header["submodel_id"].asInteger() : false;
+
+	static const std::string lod_name[] = 
 	{
 		"lowest_lod",
 		"low_lod",
@@ -2041,8 +1153,8 @@ bool LLModel::loadModel(std::istream& is)
 
 	S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS);
 
-	if (header[nm[lod]]["offset"].asInteger() == -1 || 
-		header[nm[lod]]["size"].asInteger() == 0 )
+	if (header[lod_name[lod]]["offset"].asInteger() == -1 || 
+		header[lod_name[lod]]["size"].asInteger() == 0 )
 	{ //cannot load requested LOD
 		LL_WARNS() << "LoD data is invalid!" << LL_ENDL;
 		return false;
@@ -2051,23 +1163,23 @@ bool LLModel::loadModel(std::istream& is)
 	bool has_skin = header["skin"]["offset"].asInteger() >=0 &&
 					header["skin"]["size"].asInteger() > 0;
 
-	if (lod == LLModel::LOD_HIGH)
+	if ((lod == LLModel::LOD_HIGH) && !mSubmodelID)
 	{ //try to load skin info and decomp info
 		std::ios::pos_type cur_pos = is.tellg();
 		loadSkinInfo(header, is);
 		is.seekg(cur_pos);
 	}
 
-	if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)
+	if ((lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) && !mSubmodelID)
 	{
 		std::ios::pos_type cur_pos = is.tellg();
 		loadDecomposition(header, is);
 		is.seekg(cur_pos);
 	}
 
-	is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
+	is.seekg(header[lod_name[lod]]["offset"].asInteger(), std::ios_base::cur);
 
-	if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()))
+	if (unpackVolumeFaces(is, header[lod_name[lod]]["size"].asInteger()))
 	{
 		if (has_skin)
 		{ 
@@ -2133,8 +1245,10 @@ bool LLModel::isMaterialListSubset( LLModel* ref )
 				break;
 			}										
 		}
+
 		if (!foundRef)
 		{
+            LL_INFOS() << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << LL_ENDL;
 			return false;
 		}
 	}
@@ -2185,41 +1299,42 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn
 	for (U32 i = 0; i < mMaterialList.size(); i++)
 	{
 		index_map[ref->mMaterialList[i]] = i;
-		if (!reorder)
-		{ //if any material name does not match reference, we need to reorder
-			reorder = ref->mMaterialList[i] != mMaterialList[i];
-		}
+		//if any material name does not match reference, we need to reorder
+		reorder |= ref->mMaterialList[i] != mMaterialList[i];
 		base_mat.insert(ref->mMaterialList[i]);
 		cur_mat.insert(mMaterialList[i]);
 	}
 
 
-	if (reorder && 
-		base_mat == cur_mat) //don't reorder if material name sets don't match
+	if (reorder &&  (base_mat == cur_mat)) //don't reorder if material name sets don't match
 	{
 		std::vector<LLVolumeFace> new_face_list;
-		new_face_list.resize(mVolumeFaces.size());
+		new_face_list.resize(mMaterialList.size());
 
 		std::vector<std::string> new_material_list;
-		new_material_list.resize(mVolumeFaces.size());
+		new_material_list.resize(mMaterialList.size());
 
 		//rebuild face list so materials have the same order 
 		//as the reference model
 		for (U32 i = 0; i < mMaterialList.size(); ++i)
 		{ 
 			U32 ref_idx = index_map[mMaterialList[i]];
-			new_face_list[ref_idx] = mVolumeFaces[i];
 
+			if (i < mVolumeFaces.size())
+			{
+				new_face_list[ref_idx] = mVolumeFaces[i];
+			}
 			new_material_list[ref_idx] = mMaterialList[i];
 		}
 
 		llassert(new_material_list == ref->mMaterialList);
 		
 		mVolumeFaces = new_face_list;
-	}
 
-	//override material list with reference model ordering
-	mMaterialList = ref->mMaterialList;
+		//override material list with reference model ordering
+		mMaterialList = ref->mMaterialList;
+	}
+	
 	return true;
 }
 
@@ -2250,7 +1365,7 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
 	S32 offset = header["physics_convex"]["offset"].asInteger();
 	S32 size = header["physics_convex"]["size"].asInteger();
 
-	if (offset >= 0 && size > 0)
+	if (offset >= 0 && size > 0 && !mSubmodelID)
 	{
 		is.seekg(offset, std::ios_base::cur);
 
@@ -2658,3 +1773,227 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
 	}
 }
 
+bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance)
+{
+	// small area check
+	{
+		LLVector4a edge1; edge1.setSub( a, b );
+		LLVector4a edge2; edge2.setSub( a, c );
+		//////////////////////////////////////////////////////////////////////////
+		/// Linden Modified
+		//////////////////////////////////////////////////////////////////////////
+
+		// If no one edge is more than 10x longer than any other edge, we weaken
+		// the tolerance by a factor of 1e-4f.
+
+		LLVector4a edge3; edge3.setSub( c, b );
+		const F32 len1sq = edge1.dot3(edge1).getF32();
+		const F32 len2sq = edge2.dot3(edge2).getF32();
+		const F32 len3sq = edge3.dot3(edge3).getF32();
+		bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
+		bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
+		bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
+		if ( abOK && acOK && cbOK )
+		{
+			tolerance *= 1e-4f;
+		}
+
+		//////////////////////////////////////////////////////////////////////////
+		/// End Modified
+		//////////////////////////////////////////////////////////////////////////
+
+		LLVector4a cross; cross.setCross3( edge1, edge2 );
+
+		LLVector4a edge1b; edge1b.setSub( b, a );
+		LLVector4a edge2b; edge2b.setSub( b, c );
+		LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
+
+		if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
+		{
+			return true;
+		}
+	}
+
+	// point triangle distance check
+	{
+		LLVector4a Q; Q.setSub(a, b);
+		LLVector4a R; R.setSub(c, b);
+
+		const F32 QQ = dot3fpu(Q, Q);
+		const F32 RR = dot3fpu(R, R);
+		const F32 QR = dot3fpu(R, Q);
+
+		volatile F32 QQRR = QQ * RR;
+		volatile F32 QRQR = QR * QR;
+		F32 Det = (QQRR - QRQR);
+
+		if( Det == 0.0f )
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
+bool validate_face(const LLVolumeFace& face)
+{
+	for (U32 i = 0; i < face.mNumIndices; ++i)
+	{
+		if (face.mIndices[i] >= face.mNumVertices)
+		{
+			LL_WARNS() << "Face has invalid index." << LL_ENDL;
+			return false;
+		}
+	}
+
+	if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+	{
+		LL_WARNS() << "Face has invalid number of indices." << LL_ENDL;
+		return false;
+	}
+
+	/*const LLVector4a scale(0.5f);
+
+	for (U32 i = 0; i < face.mNumIndices; i+=3)
+	{
+		U16 idx1 = face.mIndices[i];
+		U16 idx2 = face.mIndices[i+1];
+		U16 idx3 = face.mIndices[i+2];
+
+		LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
+		LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
+		LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
+
+		if (ll_is_degenerate(v1,v2,v3))
+		{
+			llwarns << "Degenerate face found!" << LL_ENDL;
+			return false;
+		}
+	}*/
+
+	return true;
+}
+
+bool validate_model(const LLModel* mdl)
+{
+	if (mdl->getNumVolumeFaces() == 0)
+	{
+		LL_WARNS() << "Model has no faces!" << LL_ENDL;
+		return false;
+	}
+
+	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+	{
+		if (mdl->getVolumeFace(i).mNumVertices == 0)
+		{
+			LL_WARNS() << "Face has no vertices." << LL_ENDL;
+			return false;
+		}
+
+		if (mdl->getVolumeFace(i).mNumIndices == 0)
+		{
+			LL_WARNS() << "Face has no indices." << LL_ENDL;
+			return false;
+		}
+
+		if (!validate_face(mdl->getVolumeFace(i)))
+		{
+			return false;
+		}
+	}
+
+	return true;
+}
+
+LLModelInstance::LLModelInstance(LLSD& data)
+	: LLModelInstanceBase()
+{
+	mLocalMeshID = data["mesh_id"].asInteger();
+	mLabel = data["label"].asString();
+	mTransform.setValue(data["transform"]);
+
+	for (U32 i = 0; i < data["material"].size(); ++i)
+	{
+		LLImportMaterial mat(data["material"][i]);
+		mMaterial[mat.mBinding] = mat;
+	}
+}
+
+
+LLSD LLModelInstance::asLLSD()
+{	
+	LLSD ret;
+
+	ret["mesh_id"] = mModel->mLocalID;
+	ret["label"] = mLabel;
+	ret["transform"] = mTransform.getValue();
+
+	U32 i = 0;
+	for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
+	{
+		ret["material"][i++] = iter->second.asLLSD();
+	}
+
+	return ret;
+}
+
+
+LLImportMaterial::~LLImportMaterial()
+{
+}
+
+LLImportMaterial::LLImportMaterial(LLSD& data)
+{
+	mDiffuseMapFilename = data["diffuse"]["filename"].asString();
+	mDiffuseMapLabel = data["diffuse"]["label"].asString();
+	mDiffuseColor.setValue(data["diffuse"]["color"]);
+	mFullbright = data["fullbright"].asBoolean();
+	mBinding = data["binding"].asString();
+}
+
+
+LLSD LLImportMaterial::asLLSD()
+{
+	LLSD ret;
+
+	ret["diffuse"]["filename"] = mDiffuseMapFilename;
+	ret["diffuse"]["label"] = mDiffuseMapLabel;
+	ret["diffuse"]["color"] = mDiffuseColor.getValue();
+	ret["fullbright"] = mFullbright;
+	ret["binding"] = mBinding;
+
+	return ret;
+}
+
+bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
+{
+
+	if (mDiffuseMapID != rhs.mDiffuseMapID)
+	{
+		return mDiffuseMapID < rhs.mDiffuseMapID;
+	}
+
+	if (mDiffuseMapFilename != rhs.mDiffuseMapFilename)
+	{
+		return mDiffuseMapFilename < rhs.mDiffuseMapFilename;
+	}
+
+	if (mDiffuseMapLabel != rhs.mDiffuseMapLabel)
+	{
+		return mDiffuseMapLabel < rhs.mDiffuseMapLabel;
+	}
+
+	if (mDiffuseColor != rhs.mDiffuseColor)
+	{
+		return mDiffuseColor < rhs.mDiffuseColor;
+	}
+
+	if (mBinding != rhs.mBinding)
+	{
+		return mBinding < rhs.mBinding;
+	}
+
+	return mFullbright < rhs.mFullbright;
+}
+
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index aaafc55258d51fac20b3016b7dea88c9d470fcb7..ae602c09df55b8098f0e3479e1e85e49f33c5b99 100755
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -31,6 +31,7 @@
 #include "llvolume.h"
 #include "v4math.h"
 #include "m4math.h"
+#include <queue>
 
 class daeElement;
 class domMesh;
@@ -138,15 +139,16 @@ class LLModel : public LLVolume
 		BOOL upload_skin,
 		BOOL upload_joints,
 		BOOL nowrite = FALSE,
-		BOOL as_slm = FALSE);
+		BOOL as_slm = FALSE,
+		int submodel_id = 0);
 
 	static LLSD writeModelToStream(
 		std::ostream& ostr,
 		LLSD& mdl,
 		BOOL nowrite = FALSE, BOOL as_slm = FALSE);
+	
+	void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); }
 
-	static LLModel* loadModelFromDomMesh(domMesh* mesh);
-	static std::string getElementLabel(daeElement* element);
 	std::string getName() const;
 	std::string getMetric() const {return mMetric;}
 	EModelStatus getStatus() const {return mStatus;}
@@ -169,20 +171,25 @@ class LLModel : public LLVolume
 
 	void addFace(const LLVolumeFace& face);
 
+	void sortVolumeFacesByMaterialName();
 	void normalizeVolumeFaces();
+	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
 	void optimizeVolumeFaces();
 	void offsetMesh( const LLVector3& pivotPoint );
 	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
 	LLVector3 getTransformedCenter(const LLMatrix4& mat);
-
+	
 	//reorder face list based on mMaterialList in this and reference so 
 	//order matches that of reference (material ordering touchup)
 	bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
 	bool isMaterialListSubset( LLModel* ref );
 	bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
 	
-	
-	std::vector<std::string> mMaterialList;
+	typedef std::vector<std::string> material_list;
+
+	material_list mMaterialList;
+
+	material_list& getMaterialList() { return mMaterialList; }
 
 	//data used for skin weights
 	class JointWeight
@@ -275,9 +282,115 @@ class LLModel : public LLVolume
 	Decomposition mPhysics;
 
 	EModelStatus mStatus ;
+
+	int mSubmodelID;
+};
+
+typedef std::vector<LLPointer<LLModel> >	model_list;
+typedef std::queue<LLPointer<LLModel> >	model_queue;
+
+class LLModelMaterialBase
+{
+public:	
+	std::string mDiffuseMapFilename;
+	std::string mDiffuseMapLabel;
+	std::string mBinding;
+	LLColor4		mDiffuseColor;
+	bool			mFullbright;
+
+	LLModelMaterialBase() 
+		: mFullbright(false) 
+	{ 
+		mDiffuseColor.set(1,1,1,1);
+	}
+};
+
+class LLImportMaterial : public LLModelMaterialBase
+{
+public:
+    friend class LLMeshUploadThread;
+    friend class LLModelPreview;
+    
+    bool operator<(const LLImportMaterial &params) const;
+    
+    LLImportMaterial() : LLModelMaterialBase()
+    {
+        mDiffuseColor.set(1,1,1,1);
+    }
+    
+    LLImportMaterial(LLSD& data);
+    virtual ~LLImportMaterial();
+    
+    LLSD asLLSD();
+    
+    const LLUUID&	getDiffuseMap() const					{ return mDiffuseMapID;		}
+    void				setDiffuseMap(const LLUUID& texId)	{ mDiffuseMapID = texId;	}
+    
 protected:
-	void addVolumeFacesFromDomMesh(domMesh* mesh);
-	virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);
+    
+    LLUUID		mDiffuseMapID;
+    void*			mOpaqueData;	// allow refs to viewer/platform-specific structs for each material
+    // currently only stores an LLPointer< LLViewerFetchedTexture > > to
+    // maintain refs to textures associated with each material for free
+    // ref counting.
 };
 
+typedef std::map<std::string, LLImportMaterial> material_map;
+
+class LLModelInstanceBase
+{
+public:
+	LLPointer<LLModel> mModel;
+	LLPointer<LLModel> mLOD[5];
+	LLUUID mMeshID;
+
+	LLMatrix4 mTransform;
+	material_map mMaterial;
+
+	LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials)
+		: mModel(model), mTransform(transform), mMaterial(materials)
+	{
+	}
+
+	LLModelInstanceBase()
+		: mModel(NULL)
+	{
+	}
+};
+
+typedef std::vector<LLModelInstanceBase> model_instance_list;
+
+class LLModelInstance : public LLModelInstanceBase
+{
+public:
+	std::string mLabel;
+	LLUUID mMeshID;
+	S32 mLocalMeshID;
+
+	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials)
+		: LLModelInstanceBase(model, transform, materials), mLabel(label)
+	{
+		mLocalMeshID = -1;
+	}
+
+	LLModelInstance(LLSD& data);
+
+	LLSD asLLSD();
+};
+
+#define LL_DEGENERACY_TOLERANCE  1e-7f
+
+inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
+{
+	volatile F32 p0 = a[0] * b[0];
+	volatile F32 p1 = a[1] * b[1];
+	volatile F32 p2 = a[2] * b[2];
+	return p0 + p1 + p2;
+}
+
+bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE);
+
+bool validate_face(const LLVolumeFace& face);
+bool validate_model(const LLModel* mdl);
+
 #endif //LL_LLMODEL_H
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81d92d151b1e911055935100bbb003c8d618dced
--- /dev/null
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -0,0 +1,640 @@
+/**
+ * @file llmodelloader.cpp
+ * @brief LLModelLoader class implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llmodelloader.h"
+#include "llsdserialize.h"
+#include "lljoint.h"
+#include "llcallbacklist.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+#include <boost/bind.hpp>
+
+std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
+
+void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
+{
+	LLVector4a box[] =
+	{
+		LLVector4a(-1, 1,-1),
+		LLVector4a(-1, 1, 1),
+		LLVector4a(-1,-1,-1),
+		LLVector4a(-1,-1, 1),
+		LLVector4a( 1, 1,-1),
+		LLVector4a( 1, 1, 1),
+		LLVector4a( 1,-1,-1),
+		LLVector4a( 1,-1, 1),
+	};
+
+	for (S32 j = 0; j < model->getNumVolumeFaces(); ++j)
+	{
+		const LLVolumeFace& face = model->getVolumeFace(j);
+
+		LLVector4a center;
+		center.setAdd(face.mExtents[0], face.mExtents[1]);
+		center.mul(0.5f);
+		LLVector4a size;
+		size.setSub(face.mExtents[1],face.mExtents[0]);
+		size.mul(0.5f);
+
+		for (U32 i = 0; i < 8; i++)
+		{
+			LLVector4a t;
+			t.setMul(size, box[i]);
+			t.add(center);
+
+			LLVector4a v;
+
+			mat.affineTransform(t, v);
+
+			if (first_transform)
+			{
+				first_transform = FALSE;
+				min = max = v;
+			}
+			else
+			{
+				update_min_max(min, max, v);
+			}
+		}
+	}
+}
+
+void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
+{
+	LLVector4a mina, maxa;
+	LLMatrix4a mata;
+
+	mata.loadu(mat);
+	mina.load3(min.mV);
+	maxa.load3(max.mV);
+
+	stretch_extents(model, mata, mina, maxa, first_transform);
+
+	min.set(mina.getF32ptr());
+	max.set(maxa.getF32ptr());
+}
+
+//-----------------------------------------------------------------------------
+// LLModelLoader
+//-----------------------------------------------------------------------------
+LLModelLoader::LLModelLoader(
+	std::string				filename,
+	S32						lod,
+	load_callback_t		load_cb,
+	joint_lookup_func_t	joint_lookup_func,
+	texture_load_func_t	texture_load_func,
+	state_callback_t		state_cb,
+	void*						opaque_userdata,
+	JointTransformMap&	jointMap,
+	JointSet&				jointsFromNodes )
+: mJointList( jointMap )
+, mJointsFromNode( jointsFromNodes )
+, LLThread("Model Loader")
+, mFilename(filename)
+, mLod(lod)
+, mFirstTransform(TRUE)
+, mNumOfFetchingTextures(0)
+, mLoadCallback(load_cb)
+, mJointLookupFunc(joint_lookup_func)
+, mTextureLoadFunc(texture_load_func)
+, mStateCallback(state_cb)
+, mOpaqueData(opaque_userdata)
+, mNoNormalize(false)
+, mNoOptimize(false)
+, mCacheOnlyHitIfRigged(false)
+{
+	mJointMap["mPelvis"] = "mPelvis";
+	mJointMap["mTorso"] = "mTorso";
+	mJointMap["mChest"] = "mChest";
+	mJointMap["mNeck"] = "mNeck";
+	mJointMap["mHead"] = "mHead";
+	mJointMap["mSkull"] = "mSkull";
+	mJointMap["mEyeRight"] = "mEyeRight";
+	mJointMap["mEyeLeft"] = "mEyeLeft";
+	mJointMap["mCollarLeft"] = "mCollarLeft";
+	mJointMap["mShoulderLeft"] = "mShoulderLeft";
+	mJointMap["mElbowLeft"] = "mElbowLeft";
+	mJointMap["mWristLeft"] = "mWristLeft";
+	mJointMap["mCollarRight"] = "mCollarRight";
+	mJointMap["mShoulderRight"] = "mShoulderRight";
+	mJointMap["mElbowRight"] = "mElbowRight";
+	mJointMap["mWristRight"] = "mWristRight";
+	mJointMap["mHipRight"] = "mHipRight";
+	mJointMap["mKneeRight"] = "mKneeRight";
+	mJointMap["mAnkleRight"] = "mAnkleRight";
+	mJointMap["mFootRight"] = "mFootRight";
+	mJointMap["mToeRight"] = "mToeRight";
+	mJointMap["mHipLeft"] = "mHipLeft";
+	mJointMap["mKneeLeft"] = "mKneeLeft";
+	mJointMap["mAnkleLeft"] = "mAnkleLeft";
+	mJointMap["mFootLeft"] = "mFootLeft";
+	mJointMap["mToeLeft"] = "mToeLeft";
+
+	mJointMap["avatar_mPelvis"] = "mPelvis";
+	mJointMap["avatar_mTorso"] = "mTorso";
+	mJointMap["avatar_mChest"] = "mChest";
+	mJointMap["avatar_mNeck"] = "mNeck";
+	mJointMap["avatar_mHead"] = "mHead";
+	mJointMap["avatar_mSkull"] = "mSkull";
+	mJointMap["avatar_mEyeRight"] = "mEyeRight";
+	mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
+	mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
+	mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
+	mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
+	mJointMap["avatar_mWristLeft"] = "mWristLeft";
+	mJointMap["avatar_mCollarRight"] = "mCollarRight";
+	mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
+	mJointMap["avatar_mElbowRight"] = "mElbowRight";
+	mJointMap["avatar_mWristRight"] = "mWristRight";
+	mJointMap["avatar_mHipRight"] = "mHipRight";
+	mJointMap["avatar_mKneeRight"] = "mKneeRight";
+	mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
+	mJointMap["avatar_mFootRight"] = "mFootRight";
+	mJointMap["avatar_mToeRight"] = "mToeRight";
+	mJointMap["avatar_mHipLeft"] = "mHipLeft";
+	mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
+	mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
+	mJointMap["avatar_mFootLeft"] = "mFootLeft";
+	mJointMap["avatar_mToeLeft"] = "mToeLeft";
+
+
+	mJointMap["hip"] = "mPelvis";
+	mJointMap["abdomen"] = "mTorso";
+	mJointMap["chest"] = "mChest";
+	mJointMap["neck"] = "mNeck";
+	mJointMap["head"] = "mHead";
+	mJointMap["figureHair"] = "mSkull";
+	mJointMap["lCollar"] = "mCollarLeft";
+	mJointMap["lShldr"] = "mShoulderLeft";
+	mJointMap["lForeArm"] = "mElbowLeft";
+	mJointMap["lHand"] = "mWristLeft";
+	mJointMap["rCollar"] = "mCollarRight";
+	mJointMap["rShldr"] = "mShoulderRight";
+	mJointMap["rForeArm"] = "mElbowRight";
+	mJointMap["rHand"] = "mWristRight";
+	mJointMap["rThigh"] = "mHipRight";
+	mJointMap["rShin"] = "mKneeRight";
+	mJointMap["rFoot"] = "mFootRight";
+	mJointMap["lThigh"] = "mHipLeft";
+	mJointMap["lShin"] = "mKneeLeft";
+	mJointMap["lFoot"] = "mFootLeft";
+
+	//move into joint mapper class
+	//1. joints for joint offset verification
+	mMasterJointList.push_front("mPelvis");
+	mMasterJointList.push_front("mTorso");
+	mMasterJointList.push_front("mChest");
+	mMasterJointList.push_front("mNeck");
+	mMasterJointList.push_front("mHead");
+	mMasterJointList.push_front("mCollarLeft");
+	mMasterJointList.push_front("mShoulderLeft");
+	mMasterJointList.push_front("mElbowLeft");
+	mMasterJointList.push_front("mWristLeft");
+	mMasterJointList.push_front("mCollarRight");
+	mMasterJointList.push_front("mShoulderRight");
+	mMasterJointList.push_front("mElbowRight");
+	mMasterJointList.push_front("mWristRight");
+	mMasterJointList.push_front("mHipRight");
+	mMasterJointList.push_front("mKneeRight");
+	mMasterJointList.push_front("mFootRight");
+	mMasterJointList.push_front("mHipLeft");
+	mMasterJointList.push_front("mKneeLeft");
+	mMasterJointList.push_front("mFootLeft");
+	
+	//2. legacy joint list - used to verify rigs that will not be using joint offsets
+	mMasterLegacyJointList.push_front("mPelvis");
+	mMasterLegacyJointList.push_front("mTorso");
+	mMasterLegacyJointList.push_front("mChest");
+	mMasterLegacyJointList.push_front("mNeck");
+	mMasterLegacyJointList.push_front("mHead");
+	mMasterLegacyJointList.push_front("mHipRight");
+	mMasterLegacyJointList.push_front("mKneeRight");
+	mMasterLegacyJointList.push_front("mFootRight");
+	mMasterLegacyJointList.push_front("mHipLeft");
+	mMasterLegacyJointList.push_front("mKneeLeft");
+	mMasterLegacyJointList.push_front("mFootLeft");
+
+	assert_main_thread();
+	sActiveLoaderList.push_back(this) ;
+}
+
+LLModelLoader::~LLModelLoader()
+{
+	assert_main_thread();
+	sActiveLoaderList.remove(this);
+}
+
+void LLModelLoader::run()
+{
+	doLoadModel();
+	doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
+}
+
+bool LLModelLoader::doLoadModel()
+{
+	//first, look for a .slm file of the same name that was modified later
+	//than the .dae
+
+	if (mTrySLM)
+	{
+		std::string filename = mFilename;
+			
+		std::string::size_type i = filename.rfind(".");
+		if (i != std::string::npos)
+		{
+			filename.replace(i, filename.size()-1, ".slm");
+			llstat slm_status;
+			if (LLFile::stat(filename, &slm_status) == 0)
+			{ //slm file exists
+				llstat dae_status;
+				if (LLFile::stat(mFilename, &dae_status) != 0 ||
+					dae_status.st_mtime < slm_status.st_mtime)
+				{
+					if (loadFromSLM(filename))
+					{ //slm successfully loaded, if this fails, fall through and
+						//try loading from dae
+
+						mLod = -1; //successfully loading from an slm implicitly sets all 
+									//LoDs
+						return true;
+					}
+				}
+			}	
+		}
+	}
+
+	return OpenFile(mFilename);
+}
+
+void LLModelLoader::setLoadState(U32 state)
+{
+	mStateCallback(state, mOpaqueData);
+}
+
+bool LLModelLoader::loadFromSLM(const std::string& filename)
+{ 
+	//only need to populate mScene with data from slm
+	llstat stat;
+
+	if (LLFile::stat(filename, &stat))
+	{ //file does not exist
+		return false;
+	}
+
+	S32 file_size = (S32) stat.st_size;
+	
+	llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary);
+	LLSD data;
+	LLSDSerialize::fromBinary(data, ifstream, file_size);
+	ifstream.close();
+
+	//build model list for each LoD
+	model_list model[LLModel::NUM_LODS];
+
+	if (data["version"].asInteger() != SLM_SUPPORTED_VERSION)
+	{  //unsupported version
+		return false;
+	}
+
+	LLSD& mesh = data["mesh"];
+
+	LLVolumeParams volume_params;
+	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
+	{
+		for (U32 i = 0; i < mesh.size(); ++i)
+		{
+			std::stringstream str(mesh[i].asString());
+			LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod);
+			if (loaded_model->loadModel(str))
+			{
+				loaded_model->mLocalID = i;
+				model[lod].push_back(loaded_model);
+
+				if (lod == LLModel::LOD_HIGH)
+				{
+					if (!loaded_model->mSkinInfo.mJointNames.empty())
+					{ 
+						//check to see if rig is valid					
+						critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );					
+					}
+					else if (mCacheOnlyHitIfRigged)
+					{
+						return false;
+					}
+				}
+			}
+		}
+	}	
+
+	if (model[LLModel::LOD_HIGH].empty())
+	{ //failed to load high lod
+		return false;
+	}
+
+	//load instance list
+	model_instance_list instance_list;
+
+	LLSD& instance = data["instance"];
+
+	for (U32 i = 0; i < instance.size(); ++i)
+	{
+		//deserialize instance list
+		instance_list.push_back(LLModelInstance(instance[i]));
+
+		//match up model instance pointers
+		S32 idx = instance_list[i].mLocalMeshID;
+		std::string instance_label = instance_list[i].mLabel;
+
+		for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
+		{
+			if (!model[lod].empty())
+			{
+				if (idx >= model[lod].size())
+				{
+					if (model[lod].size())
+					{
+						instance_list[i].mLOD[lod] = model[lod][0];
+					}
+					else
+					{
+						instance_list[i].mLOD[lod] = NULL;
+					}					
+					continue;
+				}
+
+				if (model[lod][idx]
+					&& model[lod][idx]->mLabel.empty()
+					&& !instance_label.empty())
+				{
+					// restore model names
+					std::string name = instance_label;
+					switch (lod)
+					{
+					case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
+					case LLModel::LOD_LOW:      name += "_LOD1"; break;
+					case LLModel::LOD_MEDIUM:   name += "_LOD2"; break;
+					case LLModel::LOD_PHYSICS:  name += "_PHYS"; break;
+					case LLModel::LOD_HIGH:                      break;
+					}
+					model[lod][idx]->mLabel = name;
+				}
+
+				instance_list[i].mLOD[lod] = model[lod][idx];
+			}
+		}
+
+		if (!instance_list[i].mModel)
+			instance_list[i].mModel = model[LLModel::LOD_HIGH][idx];
+	}
+
+	// Set name for UI to use
+	std::string name = data["name"];
+	if (!name.empty())
+	{
+		model[LLModel::LOD_HIGH][0]->mRequestedLabel = name;
+	}
+
+
+	//convert instance_list to mScene
+	mFirstTransform = TRUE;
+	for (U32 i = 0; i < instance_list.size(); ++i)
+	{
+		LLModelInstance& cur_instance = instance_list[i];
+		mScene[cur_instance.mTransform].push_back(cur_instance);
+		stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
+	}
+	
+	setLoadState( DONE );
+
+	return true;
+}
+
+//static
+bool LLModelLoader::isAlive(LLModelLoader* loader)
+{
+	if(!loader)
+	{
+		return false ;
+	}
+
+	std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ;
+	for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ;
+	
+	return *iter == loader ;
+}
+
+void LLModelLoader::loadModelCallback()
+{
+	mLoadCallback(mScene,mModelList,mLod, mOpaqueData);
+
+	while (!isStopped())
+	{ //wait until this thread is stopped before deleting self
+		apr_sleep(100);
+	}
+
+	//double check if "this" is valid before deleting it, in case it is aborted during running.
+	if(!isAlive(this))
+	{
+		return ;
+	}
+
+	delete this;
+}
+
+//-----------------------------------------------------------------------------
+// critiqueRigForUploadApplicability()
+//-----------------------------------------------------------------------------
+void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
+{
+	critiqueJointToNodeMappingFromScene();
+	
+	//Determines the following use cases for a rig:
+	//1. It is suitable for upload with skin weights & joint positions, or
+	//2. It is suitable for upload as standard av with just skin weights
+	
+	bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
+	bool isRigLegacyOK			 = isRigLegacy( jointListFromAsset );
+
+	//It's OK that both could end up being true, both default to false
+	if ( isJointPositionUploadOK )
+	{
+		setRigValidForJointPositionUpload( true );
+	}
+
+	if ( isRigLegacyOK) 
+	{	
+		setLegacyRigValid( true );
+	}
+
+}
+//-----------------------------------------------------------------------------
+// critiqueJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLModelLoader::critiqueJointToNodeMappingFromScene( void  )
+{
+	//Do the actual nodes back the joint listing from the dae?
+	//if yes then this is a fully rigged asset, otherwise it's just a partial rig
+	
+	JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin();
+	JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end();
+	bool result = true;
+
+	if ( !mJointsFromNode.empty() )
+	{
+		for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
+		{
+			std::string name = *jointsFromNodeIt;
+			if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
+			{
+				continue;
+			}
+			else
+			{
+				LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL;
+				result = false;				
+			}
+		}
+	}
+	else
+	{
+		result = false;
+	}
+
+	//Determines the following use cases for a rig:
+	//1. Full av rig  w/1-1 mapping from the scene and joint array
+	//2. Partial rig but w/o parity between the scene and joint array
+	if ( result )
+	{		
+		setRigWithSceneParity( true );
+	}	
+}
+//-----------------------------------------------------------------------------
+// isRigLegacy()
+//-----------------------------------------------------------------------------
+bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
+{
+	//No joints in asset
+	if ( jointListFromAsset.size() == 0 )
+	{
+		return false;
+	}
+
+	bool result = false;
+
+	JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin();	
+	JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
+	
+	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
+	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
+	
+	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
+	{
+		result = false;
+		modelJointIt = jointListFromAsset.begin();
+
+		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
+		{
+			if ( *masterJointIt == *modelJointIt )
+			{
+				result = true;
+				break;
+			}			
+		}		
+		if ( !result )
+		{
+			LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
+			break;
+		}
+	}	
+	return result;
+}
+//-----------------------------------------------------------------------------
+// isRigSuitableForJointPositionUpload()
+//-----------------------------------------------------------------------------
+bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
+{
+	bool result = false;
+
+	JointSet :: const_iterator masterJointIt = mMasterJointList.begin();	
+	JointSet :: const_iterator masterJointEndIt = mMasterJointList.end();
+	
+	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
+	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
+	
+	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
+	{
+		result = false;
+		modelJointIt = jointListFromAsset.begin();
+
+		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
+		{
+			if ( *masterJointIt == *modelJointIt )
+			{
+				result = true;
+				break;
+			}			
+		}		
+		if ( !result )
+		{
+			LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
+			break;
+		}
+	}	
+	return result;
+}
+
+
+//called in the main thread
+void LLModelLoader::loadTextures()
+{
+	BOOL is_paused = isPaused() ;
+	pause() ; //pause the loader 
+
+	for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter)
+	{
+		for(U32 i = 0 ; i < iter->second.size(); i++)
+		{
+			for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin();
+				j != iter->second[i].mMaterial.end(); ++j)
+			{
+				LLImportMaterial& material = j->second;
+
+				if(!material.mDiffuseMapFilename.empty())
+				{
+					mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData);					
+				}
+			}
+		}
+	}
+
+	if(!is_paused)
+	{
+		unpause() ;
+	}
+}
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb4d06dca3c5f9a43de3b322d77d3f535c88207d
--- /dev/null
+++ b/indra/llprimitive/llmodelloader.h
@@ -0,0 +1,212 @@
+/**
+ * @file llmodelloader.h
+ * @brief LLModelLoader class definition
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMODELLOADER_H
+#define LL_LLMODELLOADER_H
+
+#include "llmodel.h"
+#include "llthread.h"
+#include <boost/function.hpp>
+#include <list>
+
+class LLJoint;
+
+typedef std::map<std::string, LLMatrix4>					JointTransformMap;
+typedef std::map<std::string, LLMatrix4>:: iterator	JointTransformMapIt;
+typedef std::map<std::string, std::string>				JointMap;
+typedef std::deque<std::string>								JointSet;
+
+const S32 SLM_SUPPORTED_VERSION	= 3;
+const S32 NUM_LOD						= 4;
+
+class LLModelLoader : public LLThread
+{
+public:
+
+	typedef std::map<std::string, LLImportMaterial>			material_map;
+	typedef std::vector<LLPointer<LLModel > >					model_list;	
+	typedef std::vector<LLModelInstance>						model_instance_list;	
+	typedef std::map<LLMatrix4, model_instance_list >		scene;
+
+	// Callback with loaded model data and loaded LoD
+	// 
+	typedef boost::function<void (scene&,model_list&,S32,void*) >		load_callback_t;
+
+	// Function to provide joint lookup by name
+	// (within preview avi skeleton, for example)
+	//
+	typedef boost::function<LLJoint* (const std::string&,void*) >		joint_lookup_func_t;
+
+	// Func to load and associate material with all it's textures,
+	// returned value is the number of textures loaded
+	// intentionally non-const so func can modify material to
+	// store platform-specific data
+	//
+	typedef boost::function<U32 (LLImportMaterial&,void*) >				texture_load_func_t;
+
+	// Callback to inform client of state changes
+	// during loading process (errors will be reported
+	// as state changes here as well)
+	//
+	typedef boost::function<void (U32,void*) >								state_callback_t;
+
+	typedef enum
+	{
+		STARTING = 0,
+		READING_FILE,
+		CREATING_FACES,
+		GENERATING_VERTEX_BUFFERS,
+		GENERATING_LOD,
+		DONE,
+		ERROR_PARSING, //basically loading failed
+		ERROR_MATERIALS,
+		ERROR_PASSWORD_REQUIRED,
+		ERROR_NEED_MORE_MEMORY,
+		ERROR_INVALID_FILE,
+		ERROR_LOADER_SETUP,
+		ERROR_INVALID_PARAMETERS,
+		ERROR_OUT_OF_RANGE,
+		ERROR_FILE_VERSION_INVALID,
+		ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code
+	} eLoadState;
+
+	U32 mState;
+	std::string mFilename;
+	
+	S32 mLod;
+	
+	LLMatrix4 mTransform;
+	BOOL mFirstTransform;
+	LLVector3 mExtents[2];
+	
+	bool mTrySLM;
+	bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
+
+	model_list		mModelList;
+	scene				mScene;
+
+	typedef std::queue<LLPointer<LLModel> > model_queue;
+
+	//queue of models that need a physics rep
+	model_queue mPhysicsQ;
+
+	//map of avatar joints as named in COLLADA assets to internal joint names
+	JointMap			mJointMap;
+	JointTransformMap&	mJointList;	
+	JointSet&			mJointsFromNode;
+
+	LLModelLoader(
+		std::string									filename,
+		S32											lod, 
+		LLModelLoader::load_callback_t		load_cb,
+		LLModelLoader::joint_lookup_func_t	joint_lookup_func,
+		LLModelLoader::texture_load_func_t	texture_load_func,
+		LLModelLoader::state_callback_t		state_cb,
+		void*											opaque_userdata,
+		JointTransformMap&						jointMap,
+		JointSet&									jointsFromNodes);
+	virtual ~LLModelLoader() ;
+
+	virtual void setNoNormalize() { mNoNormalize = true; }
+	virtual void setNoOptimize() { mNoOptimize = true; }
+
+	virtual void run();
+	
+	// Will try SLM or derived class OpenFile as appropriate
+	//
+	virtual bool doLoadModel();
+
+	// Derived classes need to provide their parsing of files here
+	//
+	virtual bool OpenFile(const std::string& filename) = 0;
+
+	bool loadFromSLM(const std::string& filename);
+	
+	void loadModelCallback();
+	void loadTextures() ; //called in the main thread.
+	void setLoadState(U32 state);
+
+	
+
+	S32 mNumOfFetchingTextures ; //updated in the main thread
+	bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
+
+	bool verifyCount( int expected, int result );
+
+	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
+	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
+	void critiqueJointToNodeMappingFromScene( void  );
+
+	//Determines if a rig is a legacy from the joint list
+	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
+
+	//Determines if a rig is suitable for upload
+	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
+
+	void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
+	const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
+
+	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
+	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
+
+	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
+	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }		
+
+	//-----------------------------------------------------------------------------
+	// isNodeAJoint()
+	//-----------------------------------------------------------------------------
+	bool isNodeAJoint(const char* name)
+	{
+		return mJointMap.find(name) != mJointMap.end();
+	}
+
+protected:
+
+	LLModelLoader::load_callback_t		mLoadCallback;
+	LLModelLoader::joint_lookup_func_t	mJointLookupFunc;
+	LLModelLoader::texture_load_func_t	mTextureLoadFunc;
+	LLModelLoader::state_callback_t		mStateCallback;
+	void*											mOpaqueData;
+
+	bool		mRigParityWithScene;
+	bool		mRigValidJointUpload;
+	bool		mLegacyRigValid;
+
+	bool		mNoNormalize;
+	bool		mNoOptimize;
+
+	JointSet				mMasterJointList;
+	JointSet				mMasterLegacyJointList;
+	JointTransformMap	mJointTransformMap;
+
+	static std::list<LLModelLoader*> sActiveLoaderList;
+	static bool isAlive(LLModelLoader* loader) ;
+};
+class LLMatrix4a;
+void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform);
+void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform);
+
+#endif  // LL_LLMODELLOADER_H
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 19edcaa27d079d9eca8ae30b0c57f9746ef67fa0..a40c3988f23c72ea218458dc2a143845853ab639 100755
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -89,6 +89,10 @@ class LLTextureEntry
 
 	bool operator==(const LLTextureEntry &rhs) const;
 	bool operator!=(const LLTextureEntry &rhs) const;
+	
+	// Added to allow use with std::map
+	//
+	bool operator <(const LLTextureEntry &rhs) const;
 
 	LLSD asLLSD() const;
 	void asLLSD(LLSD& sd) const;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 52738aeb6fbb5b27ab90206727151e5e70e560dc..7fb1db15fb232128978c99d56edba439e06cfd20 100755
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -8,13 +8,16 @@ include(LLImage)
 include(LLInventory)
 include(LLMath)
 include(LLMessage)
+include(LLCoreHttp)
 include(LLRender)
 include(LLWindow)
+include(LLCoreHttp)
 include(LLVFS)
 include(LLXML)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLIMAGE_INCLUDE_DIRS}
     ${LLINVENTORY_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
@@ -268,16 +271,18 @@ add_library (llui ${llui_SOURCE_FILES})
 # Libraries on which this library depends, needed for Linux builds
 # Sort by high-level to low-level
 target_link_libraries(llui
-    ${LLMESSAGE_LIBRARIES}
     ${LLRENDER_LIBRARIES}
     ${LLWINDOW_LIBRARIES}
     ${LLIMAGE_LIBRARIES}
     ${LLINVENTORY_LIBRARIES}
+    ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLVFS_LIBRARIES}    # ugh, just for LLDir
     ${LLXUIXML_LIBRARIES}
     ${LLXML_LIBRARIES}
     ${LLMATH_LIBRARIES}
     ${HUNSPELL_LIBRARY}
+    ${LLMESSAGE_LIBRARIES}
     ${LLCOMMON_LIBRARIES} # must be after llimage, llwindow, llrender
     )
 
@@ -289,6 +294,8 @@ if(LL_TESTS)
       )
   LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
   # INTEGRATION TESTS
-  set(test_libs llui llmessage llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
-  LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}")
+  set(test_libs llui llmessage llcorehttp llcommon ${LLCOMMON_LIBRARIES} ${BOOST_COROUTINE_LIBRARY} ${BOOST_CONTEXT_LIBRARY} ${BOOST_SYSTEM_LIBRARY} ${WINDOWS_LIBRARIES})
+  if(NOT LINUX)
+    LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}")
+  endif(NOT LINUX)
 endif(LL_TESTS)
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 6db0d88998f3f8f2c012fc3c057e6f782baa14c9..72ff89f33c95854923d99aeb583badee42e45dda 100755
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -957,7 +957,7 @@ std::string LLUrlEntryObjectIM::getLocation(const std::string &url) const
 // LLUrlEntryParcel statics.
 LLUUID	LLUrlEntryParcel::sAgentID(LLUUID::null);
 LLUUID	LLUrlEntryParcel::sSessionID(LLUUID::null);
-LLHost	LLUrlEntryParcel::sRegionHost(LLHost::invalid);
+LLHost	LLUrlEntryParcel::sRegionHost;
 bool	LLUrlEntryParcel::sDisconnected(false);
 std::set<LLUrlEntryParcel*> LLUrlEntryParcel::sParcelInfoObservers;
 
@@ -1006,7 +1006,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC
 
 void LLUrlEntryParcel::sendParcelInfoRequest(const LLUUID& parcel_id)
 {
-	if (sRegionHost == LLHost::invalid || sDisconnected) return;
+	if (sRegionHost.isInvalid() || sDisconnected) return;
 
 	LLMessageSystem *msg = gMessageSystem;
 	msg->newMessage("ParcelInfoRequest");
@@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const
         return LLTrans::getString("ExperienceNameNull");
     }
 
-    const LLSD& experience_details = LLExperienceCache::get(experience_id);
+    const LLSD& experience_details = LLExperienceCache::instance().get(experience_id);
     if(!experience_details.isUndefined())
     {
 		std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString();
@@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const
     }
 
     addObserver(experience_id_string, url, cb);
-    LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1));
+    LLExperienceCache::instance().get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1));
     return LLTrans::getString("LoadingData");
 
 }
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index 5d3f9ac327be6352eeb877da19519ddc0dac443c..f01178c374c6fac0c30026c6c9100979e5d7842c 100755
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -165,8 +165,6 @@ LLFontGL* LLFontGL::getFontDefault()
 char const* const _PREHASH_AgentData = (char *)"AgentData";
 char const* const _PREHASH_AgentID = (char *)"AgentID";
 
-LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS);
-
 LLMessageSystem* gMessageSystem = NULL;
 
 //
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 15f2354552f06aad590201e36c9ef74e3651ad31..ba1cc436f9d30160cb06b9b92b0730f36bf40875 100755
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -37,17 +37,17 @@
 #include <boost/regex.hpp>
 
 
-namespace LLExperienceCache
-{
-    const LLSD& get( const LLUUID& key)
-    {
-		static LLSD boo;
-        return boo;
-    }
-
-    void get( const LLUUID& key, callback_slot_t slot ){}
-
-}
+// namespace LLExperienceCache
+// {
+//     const LLSD& get( const LLUUID& key)
+//     {
+// 		static LLSD boo;
+//         return boo;
+//     }
+// 
+//     void get( const LLUUID& key, callback_slot_t slot ){}
+// 
+// }
 
 typedef std::map<std::string, LLControlGroup*> settings_map_t;
 settings_map_t LLUI::sSettingGroups;
diff --git a/indra/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt
index c59645bd70e45b7d3d9a5fdbcbea3de6a7727821..ab2038826101bf3e1bb1f1fce3fbe9267e711c8e 100755
--- a/indra/mac_crash_logger/CMakeLists.txt
+++ b/indra/mac_crash_logger/CMakeLists.txt
@@ -4,6 +4,7 @@ project(mac_crash_logger)
 
 include(00-Common)
 include(LLCommon)
+include(LLCoreHttp)
 include(LLCrashLogger)
 include(LLMath)
 include(LLMessage)
@@ -11,8 +12,10 @@ include(LLVFS)
 include(LLXML)
 include(Linking)
 include(LLSharedLibs)
+include(Boost)
 
 include_directories(
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLCRASHLOGGER_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
@@ -71,7 +74,10 @@ target_link_libraries(mac-crash-logger
     ${LLMESSAGE_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_COROUTINE_LIBRARY}
     )
 
 add_custom_command(
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 536c7740bbe80622994a10421d210ca7477e19e1..07c0cb795e3a04e6fdb297ddd171730dd0997652 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -123,8 +123,6 @@ set(viewer_SOURCE_FILES
     llappearancemgr.cpp
     llappviewer.cpp
     llappviewerlistener.cpp
-    llassetuploadqueue.cpp
-    llassetuploadresponders.cpp
     llattachmentsmgr.cpp
     llaudiosourcevo.cpp
     llautoreplace.cpp
@@ -140,10 +138,7 @@ set(viewer_SOURCE_FILES
     llbreadcrumbview.cpp
     llbrowsernotification.cpp
     llbuycurrencyhtml.cpp
-    llcallbacklist.cpp
     llcallingcard.cpp
-    llcapabilitylistener.cpp
-    llcaphttpsender.cpp
     llchannelmanager.cpp
     llchatbar.cpp
     llchathistory.cpp
@@ -152,7 +147,6 @@ set(viewer_SOURCE_FILES
     llchiclet.cpp
     llchicletbar.cpp
     llclassifiedinfo.cpp
-    llclassifiedstatsresponder.cpp
     llcofwearables.cpp
     llcolorswatch.cpp
     llcommanddispatcherlistener.cpp
@@ -197,7 +191,6 @@ set(viewer_SOURCE_FILES
     lleventnotifier.cpp
     lleventpoll.cpp
     llexpandabletextbox.cpp
-    llexperienceassociationresponder.cpp
     llexperiencelog.cpp
     llexternaleditor.cpp
     llface.cpp
@@ -234,7 +227,6 @@ set(viewer_SOURCE_FILES
     llfloaterconversationpreview.cpp
     llfloaterdeleteenvpreset.cpp
     llfloaterdestinations.cpp
-    llfloaterdisplayname.cpp
     llfloatereditdaycycle.cpp
     llfloatereditsky.cpp
     llfloatereditwater.cpp
@@ -277,7 +269,6 @@ set(viewer_SOURCE_FILES
     llfloaternotificationsconsole.cpp
     llfloaterobjectweights.cpp
     llfloateropenobject.cpp
-    llfloateroutbox.cpp
     llfloaterpathfindingcharacters.cpp
     llfloaterpathfindingconsole.cpp
     llfloaterpathfindinglinksets.cpp
@@ -334,7 +325,6 @@ set(viewer_SOURCE_FILES
     llgroupmgr.cpp
     llhasheduniqueid.cpp
     llhints.cpp
-    llhomelocationresponder.cpp
     llhttpretrypolicy.cpp
     llhudeffect.cpp
     llhudeffectbeam.cpp
@@ -569,7 +559,6 @@ set(viewer_SOURCE_FILES
     lltextureinfo.cpp
     lltextureinfodetails.cpp
     lltexturestats.cpp
-    lltexturestatsuploader.cpp
     lltextureview.cpp
     lltoast.cpp
     lltoastalertpanel.cpp
@@ -605,7 +594,6 @@ set(viewer_SOURCE_FILES
     lltwitterconnect.cpp
     lluilistener.cpp
     lluploaddialog.cpp
-    lluploadfloaterobservers.cpp
     llurl.cpp
     llurldispatcher.cpp
     llurldispatcherlistener.cpp
@@ -618,6 +606,7 @@ set(viewer_SOURCE_FILES
     llviewerassetstats.cpp
     llviewerassetstorage.cpp
     llviewerassettype.cpp
+    llviewerassetupload.cpp
     llviewerattachmenu.cpp
     llvieweraudio.cpp
     llviewercamera.cpp
@@ -625,7 +614,6 @@ set(viewer_SOURCE_FILES
     llviewercontrol.cpp
     llviewercontrollistener.cpp
     llviewerdisplay.cpp
-    llviewerdisplayname.cpp
     llviewerfloaterreg.cpp
     llviewerfoldertype.cpp
     llviewergenericmessage.cpp
@@ -740,8 +728,6 @@ set(viewer_HEADER_FILES
     llappearancemgr.h
     llappviewer.h
     llappviewerlistener.h
-    llassetuploadqueue.h
-    llassetuploadresponders.h
     llattachmentsmgr.h
     llaudiosourcevo.h
     llautoreplace.h
@@ -756,11 +742,8 @@ set(viewer_HEADER_FILES
     llbox.h
     llbreadcrumbview.h
     llbuycurrencyhtml.h
-    llcallbacklist.h
     llcallingcard.h
-    llcapabilitylistener.h
     llcapabilityprovider.h
-    llcaphttpsender.h
     llchannelmanager.h
     llchatbar.h
     llchathistory.h
@@ -769,7 +752,6 @@ set(viewer_HEADER_FILES
     llchiclet.h
     llchicletbar.h
     llclassifiedinfo.h
-    llclassifiedstatsresponder.h
     llcofwearables.h
     llcolorswatch.h
     llcommanddispatcherlistener.h
@@ -814,7 +796,6 @@ set(viewer_HEADER_FILES
     lleventnotifier.h
     lleventpoll.h
     llexpandabletextbox.h
-    llexperienceassociationresponder.h
     llexperiencelog.h
     llexternaleditor.h
     llface.h
@@ -851,7 +832,6 @@ set(viewer_HEADER_FILES
     llfloaterconversationpreview.h
     llfloaterdeleteenvpreset.h
     llfloaterdestinations.h
-    llfloaterdisplayname.h
     llfloatereditdaycycle.h
     llfloatereditsky.h
     llfloatereditwater.h
@@ -897,7 +877,6 @@ set(viewer_HEADER_FILES
     llfloaternotificationsconsole.h
     llfloaterobjectweights.h
     llfloateropenobject.h
-    llfloateroutbox.h
     llfloaterpathfindingcharacters.h
     llfloaterpathfindingconsole.h
     llfloaterpathfindinglinksets.h
@@ -954,7 +933,6 @@ set(viewer_HEADER_FILES
     llhasheduniqueid.h
     llhints.h
     llhttpretrypolicy.h
-    llhomelocationresponder.h
     llhudeffect.h
     llhudeffectbeam.h
     llhudeffectlookat.h
@@ -1177,7 +1155,6 @@ set(viewer_HEADER_FILES
     lltextureinfo.h
     lltextureinfodetails.h
     lltexturestats.h
-    lltexturestatsuploader.h
     lltextureview.h
     lltoast.h
     lltoastalertpanel.h
@@ -1227,6 +1204,7 @@ set(viewer_HEADER_FILES
     llviewerassetstats.h
     llviewerassetstorage.h
     llviewerassettype.h
+    llviewerassetupload.h
     llviewerattachmenu.h
     llvieweraudio.h
     llviewercamera.h
@@ -1234,7 +1212,6 @@ set(viewer_HEADER_FILES
     llviewercontrol.h
     llviewercontrollistener.h
     llviewerdisplay.h
-    llviewerdisplayname.h
     llviewerfloaterreg.h
     llviewerfoldertype.h
     llviewergenericmessage.h
@@ -1985,8 +1962,8 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${viewer_LIBRARIES}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
     ${BOOST_REGEX_LIBRARY}
-    ${BOOST_CONTEXT_LIBRARY}
     ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
     ${DBUSGLIB_LIBRARIES}
     ${OPENGL_LIBRARIES}
     ${FMODWRAPPER_LIBRARY} # must come after LLAudio
@@ -2240,10 +2217,9 @@ if (LL_TESTS)
   SET(viewer_TEST_SOURCE_FILES
     llagentaccess.cpp
     lldateutil.cpp
-    llmediadataclient.cpp
+#    llmediadataclient.cpp
     lllogininstance.cpp
-    llremoteparcelrequest.cpp
-    lltranslate.cpp
+#    llremoteparcelrequest.cpp
     llviewerhelputil.cpp
     llversioninfo.cpp
     llworldmap.cpp
@@ -2264,16 +2240,10 @@ if (LL_TESTS)
     ${CURL_LIBRARIES}
     )
 
-  set_source_files_properties(
-    lltranslate.cpp
-    PROPERTIES
-    LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
-  )
-
   set_source_files_properties(
     llmediadataclient.cpp
     PROPERTIES
-    LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}"
+    LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
   )
 
   set_source_files_properties(
@@ -2329,7 +2299,6 @@ if (LL_TESTS)
   LL_ADD_PROJECT_UNIT_TESTS(${VIEWER_BINARY_NAME} "${viewer_TEST_SOURCE_FILES}")
 
   #set(TEST_DEBUG on)
-  set(test_sources llcapabilitylistener.cpp)
   ##################################################
   # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
   ##################################################
@@ -2345,26 +2314,29 @@ if (LL_TESTS)
     ${GOOGLEMOCK_LIBRARIES}
     )
 
-  LL_ADD_INTEGRATION_TEST(llcapabilitylistener
-    "${test_sources}"
-    "${test_libs}"
-    ${PYTHON_EXECUTABLE}
-    "${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py"
-    )
+  if (LINUX)
+    # llcommon uses `clock_gettime' which is provided by librt on linux.
+    set(LIBRT_LIBRARY
+      rt
+      )
+  endif (LINUX)
 
   set(test_libs
-    ${LLMESSAGE_LIBRARIES}
-    ${LLCOREHTTP_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLMATH_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${GOOGLEMOCK_LIBRARIES}
     ${OPENSSL_LIBRARIES}
     ${CRYPTO_LIBRARIES}
+    ${LIBRT_LIBRARY}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
   )
 
-    LL_ADD_INTEGRATION_TEST(llsechandler_basic
+  LL_ADD_INTEGRATION_TEST(llsechandler_basic
     llsechandler_basic.cpp
     "${test_libs}"
     )
@@ -2395,13 +2367,12 @@ if (LL_TESTS)
     "${test_libs}"
     )
 
-  LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}")
+# LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}")
 
   #ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
   #ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
   #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
   #ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
-  #ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
 
 include(LLAddBuildTest)
 SET(viewer_TEST_SOURCE_FILES
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index ff313b8c212f86ecce5e9ce1db1b5a17b83d134a..0cbfaed0d9fe75138f385fed8aff02d7ca8a0880 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.8.4
+3.8.5
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 0371a819ddc3b2030c31d9c1a6a14a9cbcb78663..81da856d7e323885f083771d664aaa3c6513c86b 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -2,6 +2,39 @@
 <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="llsd.xsd">
 <map>
+  <key>ImporterDebug</key>
+  <map>
+    <key>Comment</key>
+    <string>Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>ImporterLegacyMatching</key>
+  <map>
+    <key>Comment</key>
+    <string>Enable index based model matching.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>ImporterModelLimit</key>
+  <map>
+    <key>Comment</key>
+    <string>Limits amount of importer generated models for dae files</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>768</integer>
+  </map>
     <key>IMShowTime</key>
     <map>
       <key>Comment</key>
@@ -2370,6 +2403,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>DebugSlshareLogTag</key>
+    <map>
+      <key>Comment</key>
+      <string>Request slshare-service debug logging</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string/>
+    </map>
   <key>DebugStatModeFPS</key>
     <map>
       <key>Comment</key>
@@ -14384,6 +14428,24 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>PoolSizeAIS</key>
+        <map>
+        <key>Comment</key>
+            <string>Coroutine Pool size for AIS</string>
+        <key>Type</key>
+            <string>U32</string>
+        <key>Value</key>
+            <integer>25</integer>
+        </map>
+    <key>PoolSizeUpload</key>
+        <map>
+        <key>Comment</key>
+            <string>Coroutine Pool size for Upload</string>
+        <key>Type</key>
+            <string>U32</string>
+        <key>Value</key>
+            <real>1</real>
+        </map>
 
     <!-- Settings below are for back compatibility only.
     They are not used in current viewer anymore. But they can't be removed to avoid
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index a42286a9e4aabc2fb9b5c7e58df02537784acd98..92a5413adb519991dbe223b73d4e9b6db1174e3e 100755
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -27,90 +27,145 @@
 #include "llviewerprecompiledheaders.h"
 #include "llaccountingcostmanager.h"
 #include "llagent.h"
-#include "llcurl.h"
-#include "llhttpclient.h"
+#include "httpcommon.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+#include <algorithm>
+#include <iterator>
+
 //===============================================================================
 LLAccountingCostManager::LLAccountingCostManager()
 {	
+
 }
-//===============================================================================
-class LLAccountingCostResponder : public LLCurl::Responder
+
+// Coroutine for sending and processing avatar name cache requests.  
+// Do not call directly.  See documentation in lleventcoro.h and llcoro.h for
+// further explanation.
+void LLAccountingCostManager::accountingCostCoro(std::string url,
+    eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle)
 {
-	LOG_CLASS(LLAccountingCostResponder);
-public:
-	LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
-	: mObjectIDs( objectIDs ),
-	  mObserverHandle( observer_handle )
-	{
-		LLAccountingCostObserver* observer = mObserverHandle.get();
-		if (observer)
-		{
-			mTransactionID = observer->getTransactionID();
-		}
-	}
+    LL_DEBUGS("LLAccountingCostManager") << "Entering coroutine " << LLCoros::instance().getName()
+        << " with url '" << url << LL_ENDL;
 
-	void clearPendingRequests ( void )
-	{
-		for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
-		{
-			LLAccountingCostManager::getInstance()->removePendingObject( iter->asUUID() );
-		}
-	}
-	
-protected:
-	void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-		clearPendingRequests();
-
-		LLAccountingCostObserver* observer = mObserverHandle.get();
-		if (observer && observer->getTransactionID() == mTransactionID)
-		{
-			observer->setErrorStatus(getStatus(), getReason());
-		}
-	}
-	
-	void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		//Check for error
-		if ( !content.isMap() || content.has("error") )
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content);
-			return;
-		}
-		else if (content.has("selected"))
-		{
-			F32 physicsCost		= 0.0f;
-			F32 networkCost		= 0.0f;
-			F32 simulationCost	= 0.0f;
-
-			physicsCost		= content["selected"]["physics"].asReal();
-			networkCost		= content["selected"]["streaming"].asReal();
-			simulationCost	= content["selected"]["simulation"].asReal();
-				
-			SelectionCost selectionCost( /*transactionID,*/ physicsCost, networkCost, simulationCost );
-
-			LLAccountingCostObserver* observer = mObserverHandle.get();
-			if (observer && observer->getTransactionID() == mTransactionID)
-			{
-				observer->onWeightsUpdate(selectionCost);
-			}
-		}
-
-		clearPendingRequests();
-	}
-	
-private:
-	//List of posted objects
-	LLSD mObjectIDs;
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AccountingCost", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    try
+    {
+        uuid_set_t diffSet;
+
+        std::set_difference(mObjectList.begin(), mObjectList.end(),
+            mPendingObjectQuota.begin(), mPendingObjectQuota.end(),
+            std::inserter(diffSet, diffSet.begin()));
+
+        if (diffSet.empty())
+            return;
+
+        mObjectList.clear();
+
+        std::string keystr;
+        if (selectionType == Roots)
+        {
+            keystr = "selected_roots";
+        }
+        else if (selectionType == Prims)
+        {
+            keystr = "selected_prims";
+        }
+        else
+        {
+            LL_INFOS() << "Invalid selection type " << LL_ENDL;
+            return;
+        }
+
+        LLSD objectList(LLSD::emptyMap());
+
+        for (uuid_set_t::iterator it = diffSet.begin(); it != diffSet.end(); ++it)
+        {
+            objectList.append(*it);
+        }
+
+        mPendingObjectQuota.insert(diffSet.begin(), diffSet.end());
+
+        LLSD dataToPost = LLSD::emptyMap();
+        dataToPost[keystr.c_str()] = objectList;
 
-	// Current request ID
-	LLUUID mTransactionID;
+        LLAccountingCostObserver* observer = observerHandle.get();
+        LLUUID transactionId = observer->getTransactionID();
+        observer = NULL;
+
+
+
+        LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost);
+
+        LLSD httpResults = results["http_result"];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+        // do/while(false) allows error conditions to break out of following 
+        // block while normal flow goes forward once.
+        do 
+        {
+            observer = observerHandle.get();
+
+            if (!status || results.has("error"))
+            {
+                LL_WARNS() << "Error on fetched data" << LL_ENDL;
+                if (!status)
+                    observer->setErrorStatus(status.getType(), status.toString());
+                else
+                    observer->setErrorStatus(499, "Error on fetched data");
+
+                break;
+            }
+
+            if (!httpResults["success"].asBoolean())
+            {
+                LL_WARNS() << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+                    << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
+                if (observer)
+                {
+                    observer->setErrorStatus(httpResults["status"].asInteger(), httpResults["message"].asStringRef());
+                }
+                break;
+            }
+
+
+            if (results.has("selected"))
+            {
+                LLSD selected = results["selected"];
+
+                F32 physicsCost = 0.0f;
+                F32 networkCost = 0.0f;
+                F32 simulationCost = 0.0f;
+
+                physicsCost = selected["physics"].asReal();
+                networkCost = selected["streaming"].asReal();
+                simulationCost = selected["simulation"].asReal();
+
+                SelectionCost selectionCost( physicsCost, networkCost, simulationCost);
+
+                observer->onWeightsUpdate(selectionCost);
+            }
+
+        } while (false);
+
+    }
+    catch (std::exception e)
+    {
+        LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
+    }
+    catch (...)
+    {
+        LL_WARNS() << "Caught unknown exception." << LL_ENDL;
+    }
+
+    mPendingObjectQuota.clear();
+}
 
-	// Cost update observer handle
-	LLHandle<LLAccountingCostObserver> mObserverHandle;
-};
 //===============================================================================
 void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
 										  const std::string& url,
@@ -119,50 +174,11 @@ void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
 	// Invoking system must have already determined capability availability
 	if ( !url.empty() )
 	{
-		LLSD objectList;
-		U32  objectIndex = 0;
-		
-		IDIt IDIter = mObjectList.begin();
-		IDIt IDIterEnd = mObjectList.end();
-		
-		for ( ; IDIter != IDIterEnd; ++IDIter )
-		{
-			// Check to see if a request for this object has already been made.
-			if ( mPendingObjectQuota.find( *IDIter ) ==	mPendingObjectQuota.end() )
-			{
-				mPendingObjectQuota.insert( *IDIter );
-				objectList[objectIndex++] = *IDIter;
-			}
-		}
-	
-		mObjectList.clear();
-		
-		//Post results
-		if ( objectList.size() > 0 )
-		{
-			std::string keystr;
-			if ( selectionType == Roots ) 
-			{ 
-				keystr="selected_roots"; 
-			}
-			else
-			if ( selectionType == Prims ) 
-			{ 
-				keystr="selected_prims";
-			}
-			else 
-			{
-				LL_INFOS()<<"Invalid selection type "<<LL_ENDL;
-				mObjectList.clear();
-				mPendingObjectQuota.clear();
-				return;
-			}
-			
-			LLSD dataToPost = LLSD::emptyMap();		
-			dataToPost[keystr.c_str()] = objectList;
-
-			LLHTTPClient::post( url, dataToPost, new LLAccountingCostResponder( objectList, observer_handle ));
-		}
+        std::string coroname = 
+            LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro",
+            boost::bind(&LLAccountingCostManager::accountingCostCoro, this, url, selectionType, observer_handle));
+        LL_DEBUGS() << coroname << " with  url '" << url << LL_ENDL;
+
 	}
 	else
 	{
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 3ade34c81d0a6c7a1be2faa010e7ffd06df4427c..f251ceffd47694742ea1cc671713a5b40ad61349 100755
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -30,6 +30,13 @@
 #include "llhandle.h"
 
 #include "llaccountingcost.h"
+#include "httpcommon.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+
 //===============================================================================
 // An interface class for panels which display the parcel accounting information.
 class LLAccountingCostObserver
@@ -64,11 +71,13 @@ class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager>
 	
 private:
 	//Set of objects that will be used to generate a cost
-	std::set<LLUUID> mObjectList;
+	uuid_set_t mObjectList;
 	//During fetchCosts we move object into a the pending set to signify that 
 	//a fetch has been instigated.
-	std::set<LLUUID> mPendingObjectQuota;
-	typedef std::set<LLUUID>::iterator IDIt;
+	uuid_set_t mPendingObjectQuota;
+
+    void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
+
 };
 //===============================================================================
 
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 092d868bb92a29b13f111ff010448bcd760c29af..3316f1e6544eb62fa195fed27c0fac5fe938b2c2 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -38,7 +38,6 @@
 #include "llappearancemgr.h"
 #include "llanimationstates.h"
 #include "llcallingcard.h"
-#include "llcapabilitylistener.h"
 #include "llchannelmanager.h"
 #include "llchicletbar.h"
 #include "llconsole.h"
@@ -52,7 +51,6 @@
 #include "llfloatertools.h"
 #include "llgroupactions.h"
 #include "llgroupmgr.h"
-#include "llhomelocationresponder.h"
 #include "llhudmanager.h"
 #include "lljoystickbutton.h"
 #include "llmorphview.h"
@@ -63,7 +61,6 @@
 #include "llpaneltopinfobar.h"
 #include "llparcel.h"
 #include "llrendersphere.h"
-#include "llsdmessage.h"
 #include "llsdutil.h"
 #include "llsky.h"
 #include "llslurl.h"
@@ -95,6 +92,7 @@
 #include "lscript_byteformat.h"
 #include "stringize.h"
 #include "boost/foreach.hpp"
+#include "llcorehttputil.h"
 
 using namespace LLAvatarAppearanceDefines;
 
@@ -361,7 +359,8 @@ LLAgent::LLAgent() :
 	mMaturityPreferenceNumRetries(0U),
 	mLastKnownRequestMaturity(SIM_ACCESS_MIN),
 	mLastKnownResponseMaturity(SIM_ACCESS_MIN),
-	mTeleportState( TELEPORT_NONE ),
+	mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+	mTeleportState(TELEPORT_NONE),
 	mRegionp(NULL),
 
 	mAgentOriginGlobal(),
@@ -461,6 +460,10 @@ void LLAgent::init()
 		mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this));
 	}
 
+	LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+
+	mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_AGENT);
+
 	mInitialized = TRUE;
 }
 
@@ -927,7 +930,7 @@ LLHost LLAgent::getRegionHost() const
 	}
 	else
 	{
-		return LLHost::invalid;
+		return LLHost();
 	}
 }
 
@@ -950,6 +953,15 @@ BOOL LLAgent::inPrelude()
 }
 
 
+std::string LLAgent::getRegionCapability(const std::string &name)
+{
+    if (!mRegionp)
+        return std::string();
+    
+    return mRegionp->getCapability(name);
+}
+
+
 //-----------------------------------------------------------------------------
 // canManageEstate()
 //-----------------------------------------------------------------------------
@@ -2326,27 +2338,9 @@ void LLAgent::setStartPosition( U32 location_id )
 
     body["HomeLocation"] = homeLocation;
 
-    // This awkward idiom warrants explanation.
-    // For starters, LLSDMessage::ResponderAdapter is ONLY for testing the new
-    // LLSDMessage functionality with a pre-existing LLHTTPClient::Responder.
-    // In new code, define your reply/error methods on the same class as the
-    // sending method, bind them to local LLEventPump objects and pass those
-    // LLEventPump names in the request LLSD object.
-    // When testing old code, the new LLHomeLocationResponder object
-    // is referenced by an LLHTTPClient::ResponderPtr, so when the
-    // ResponderAdapter is deleted, the LLHomeLocationResponder will be too.
-    // We must trust that the underlying LLHTTPClient code will eventually
-    // fire either the reply callback or the error callback; either will cause
-    // the ResponderAdapter to delete itself.
-    LLSDMessage::ResponderAdapter*
-        adapter(new LLSDMessage::ResponderAdapter(new LLHomeLocationResponder()));
-
-    request["message"] = "HomeLocation";
-    request["payload"] = body;
-    request["reply"]   = adapter->getReplyName();
-    request["error"]   = adapter->getErrorName();
-
-    gAgent.getRegion()->getCapAPI().post(request);
+    if (!requestPostCapability("HomeLocation", body, 
+            boost::bind(&LLAgent::setStartPositionSuccess, this, _1)))
+        LL_WARNS() << "Unable to post to HomeLocation capability." << LL_ENDL;
 
     const U32 HOME_INDEX = 1;
     if( HOME_INDEX == location_id )
@@ -2355,32 +2349,51 @@ void LLAgent::setStartPosition( U32 location_id )
     }
 }
 
-struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper
+void LLAgent::setStartPositionSuccess(const LLSD &result)
 {
-    // No reply message expected
-    HomeLocationMapper(): LLCapabilityListener::CapabilityMapper("HomeLocation") {}
-    virtual void buildMessage(LLMessageSystem* msg,
-                              const LLUUID& agentID,
-                              const LLUUID& sessionID,
-                              const std::string& capabilityName,
-                              const LLSD& payload) const
+    LLVector3 agent_pos;
+    bool      error = true;
+
+    do {
+        // was the call to /agent/<agent-id>/home-location successful?
+        // If not, we keep error set to true
+        if (!result.has("success"))
+            break;
+
+        if (0 != strncmp("true", result["success"].asString().c_str(), 4))
+            break;
+
+        // did the simulator return a "justified" home location?
+        // If no, we keep error set to true
+        if (!result.has("HomeLocation"))
+            break;
+
+        if ((!result["HomeLocation"].has("LocationPos")) ||
+                (!result["HomeLocation"]["LocationPos"].has("X")) ||
+                (!result["HomeLocation"]["LocationPos"].has("Y")) ||
+                (!result["HomeLocation"]["LocationPos"].has("Z")))
+            break;
+
+        agent_pos.mV[VX] = result["HomeLocation"]["LocationPos"]["X"].asInteger();
+        agent_pos.mV[VY] = result["HomeLocation"]["LocationPos"]["Y"].asInteger();
+        agent_pos.mV[VZ] = result["HomeLocation"]["LocationPos"]["Z"].asInteger();
+
+        error = false;
+
+    } while (0);
+
+    if (error)
     {
-        msg->newMessageFast(_PREHASH_SetStartLocationRequest);
-        msg->nextBlockFast( _PREHASH_AgentData);
-        msg->addUUIDFast(_PREHASH_AgentID, agentID);
-        msg->addUUIDFast(_PREHASH_SessionID, sessionID);
-        msg->nextBlockFast( _PREHASH_StartLocationData);
-        // corrected by sim
-        msg->addStringFast(_PREHASH_SimName, "");
-        msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
-        msg->addVector3Fast(_PREHASH_LocationPos,
-                            ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
-        msg->addVector3Fast(_PREHASH_LocationLookAt,
-                            ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
+        LL_WARNS() << "Error in response to home position set." << LL_ENDL;
     }
-};
-// Need an instance of this class so it will self-register
-static HomeLocationMapper homeLocationMapper;
+    else
+    {
+        LL_INFOS() << "setting home position" << LL_ENDL;
+
+        LLViewerRegion *viewer_region = gAgent.getRegion();
+        setHomePosRegion(viewer_region->getHandle(), agent_pos);
+    }
+}
 
 void LLAgent::requestStopMotion( LLMotion* motion )
 {
@@ -2517,87 +2530,6 @@ int LLAgent::convertTextToMaturity(char text)
 	return LLAgentAccess::convertTextToMaturity(text);
 }
 
-class LLMaturityPreferencesResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLMaturityPreferencesResponder);
-public:
-	LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity);
-	virtual ~LLMaturityPreferencesResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-protected:
-
-private:
-	U8 parseMaturityFromServerResponse(const LLSD &pContent) const;
-
-	LLAgent                                  *mAgent;
-	U8                                       mPreferredMaturity;
-	U8                                       mPreviousMaturity;
-};
-
-LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity)
-	: LLHTTPClient::Responder(),
-	mAgent(pAgent),
-	mPreferredMaturity(pPreferredMaturity),
-	mPreviousMaturity(pPreviousMaturity)
-{
-}
-
-LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder()
-{
-}
-
-void LLMaturityPreferencesResponder::httpSuccess()
-{
-	U8 actualMaturity = parseMaturityFromServerResponse(getContent());
-
-	if (actualMaturity != mPreferredMaturity)
-	{
-		LL_WARNS() << "while attempting to change maturity preference from '"
-				   << LLViewerRegion::accessToString(mPreviousMaturity)
-				   << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
-				   << "', the server responded with '"
-				   << LLViewerRegion::accessToString(actualMaturity) 
-				   << "' [value:" << static_cast<U32>(actualMaturity) 
-				   << "], " << dumpResponse() << LL_ENDL;
-	}
-	mAgent->handlePreferredMaturityResult(actualMaturity);
-}
-
-void LLMaturityPreferencesResponder::httpFailure()
-{
-	LL_WARNS() << "while attempting to change maturity preference from '" 
-			   << LLViewerRegion::accessToString(mPreviousMaturity)
-			   << "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) 
-			<< "', " << dumpResponse() << LL_ENDL;
-	mAgent->handlePreferredMaturityError();
-}
-
-U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent) const
-{
-	U8 maturity = SIM_ACCESS_MIN;
-
-	llassert(pContent.isDefined());
-	llassert(pContent.isMap());
-	llassert(pContent.has("access_prefs"));
-	llassert(pContent.get("access_prefs").isMap());
-	llassert(pContent.get("access_prefs").has("max"));
-	llassert(pContent.get("access_prefs").get("max").isString());
-	if (pContent.isDefined() && pContent.isMap() && pContent.has("access_prefs")
-		&& pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max")
-		&& pContent.get("access_prefs").get("max").isString())
-	{
-		LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString();
-		LLStringUtil::trim(actualPreference);
-		maturity = LLViewerRegion::shortStringToAccess(actualPreference);
-	}
-
-	return maturity;
-}
-
 void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity)
 {
 	// Update the number of responses received
@@ -2726,42 +2658,96 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
 		// Update the last know maturity request
 		mLastKnownRequestMaturity = pPreferredMaturity;
 
-		// Create a response handler
-		LLHTTPClient::ResponderPtr responderPtr = LLHTTPClient::ResponderPtr(new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity));
-
 		// If we don't have a region, report it as an error
 		if (getRegion() == NULL)
 		{
-			responderPtr->failureResult(0U, "region is not defined", LLSD());
+			LL_WARNS("Agent") << "Region is not defined, can not change Maturity setting." << LL_ENDL;
+			return;
 		}
-		else
-		{
-			// Find the capability to send maturity preference
-			std::string url = getRegion()->getCapability("UpdateAgentInformation");
 
-			// If the capability is not defined, report it as an error
-			if (url.empty())
-			{
-				responderPtr->failureResult(0U, 
-							"capability 'UpdateAgentInformation' is not defined for region", LLSD());
-			}
-			else
-			{
-				// Set new access preference
-				LLSD access_prefs = LLSD::emptyMap();
-				access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity);
-
-				LLSD body = LLSD::emptyMap();
-				body["access_prefs"] = access_prefs;
-				LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity)
-					<< "' via capability to: " << url << LL_ENDL;
-				LLSD headers;
-				LLHTTPClient::post(url, body, responderPtr, headers, 30.0f);
-			}
-		}
+		LLSD access_prefs = LLSD::emptyMap();
+		access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity);
+
+		LLSD postData = LLSD::emptyMap();
+		postData["access_prefs"] = access_prefs;
+		LL_INFOS() << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity) << LL_ENDL;
+
+        if (!requestPostCapability("UpdateAgentInformation", postData,
+            static_cast<httpCallback_t>(boost::bind(&LLAgent::processMaturityPreferenceFromServer, this, _1, pPreferredMaturity)),
+            static_cast<httpCallback_t>(boost::bind(&LLAgent::handlePreferredMaturityError, this))
+            ))
+        {
+            LL_WARNS("Agent") << "Maturity request post failed." << LL_ENDL;
+        }
 	}
 }
 
+
+void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity)
+{
+    U8 maturity = SIM_ACCESS_MIN;
+
+    llassert(result.isDefined());
+    llassert(result.isMap());
+    llassert(result.has("access_prefs"));
+    llassert(result.get("access_prefs").isMap());
+    llassert(result.get("access_prefs").has("max"));
+    llassert(result.get("access_prefs").get("max").isString());
+    if (result.isDefined() && result.isMap() && result.has("access_prefs")
+        && result.get("access_prefs").isMap() && result.get("access_prefs").has("max")
+        && result.get("access_prefs").get("max").isString())
+    {
+        LLSD::String actualPreference = result.get("access_prefs").get("max").asString();
+        LLStringUtil::trim(actualPreference);
+        maturity = LLViewerRegion::shortStringToAccess(actualPreference);
+    }
+
+    if (maturity != perferredMaturity)
+    {
+        LL_WARNS() << "while attempting to change maturity preference from '"
+            << LLViewerRegion::accessToString(mLastKnownResponseMaturity)
+            << "' to '" << LLViewerRegion::accessToString(perferredMaturity)
+            << "', the server responded with '"
+            << LLViewerRegion::accessToString(maturity)
+            << "' [value:" << static_cast<U32>(maturity)
+            << "], " << LL_ENDL;
+    }
+    handlePreferredMaturityResult(maturity);
+}
+
+
+bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
+{
+    std::string url;
+
+    url = getRegion()->getCapability(capName);
+
+    if (url.empty())
+    {
+        LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
+        return false;
+    }
+
+    LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, mHttpPolicy, postData, cbSuccess, cbFailure);
+    return true;
+}
+
+bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure)
+{
+    std::string url;
+
+    url = getRegion()->getCapability(capName);
+
+    if (url.empty())
+    {
+        LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
+        return false;
+    }
+
+    LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, mHttpPolicy, cbSuccess, cbFailure);
+    return true;
+}
+
 BOOL LLAgent::getAdminOverride() const	
 { 
 	return mAgentAccess->getAdminOverride(); 
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 4830cb754b6654dd89f6db6d366d1f3eb7e289cb..5731f4db89a07ea691accb740bffbc6565a273ee 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -34,7 +34,9 @@
 #include "llcoordframe.h"			// for mFrameAgent
 #include "llavatarappearancedefines.h"
 #include "llpermissionsflags.h"
+#include "llevents.h"
 #include "v3dmath.h"
+#include "llcorehttputil.h"
 
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
@@ -61,6 +63,8 @@ class LLPauseRequestHandle;
 class LLUIColor;
 class LLTeleportRequest;
 
+
+
 typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr;
 
 //--------------------------------------------------------------------
@@ -112,6 +116,8 @@ class LLAgent : public LLOldEvents::LLObservable
 	void			init();
 	void			cleanup();
 
+private:
+
 	//--------------------------------------------------------------------
 	// Login
 	//--------------------------------------------------------------------
@@ -227,6 +233,8 @@ class LLAgent : public LLOldEvents::LLObservable
 	void			setHomePosRegion(const U64& region_handle, const LLVector3& pos_region);
 	BOOL			getHomePosGlobal(LLVector3d* pos_global);
 private:
+    void            setStartPositionSuccess(const LLSD &result);
+
 	BOOL 			mHaveHomePosition;
 	U64				mHomeRegionHandle;
 	LLVector3		mHomePosRegion;
@@ -254,6 +262,9 @@ class LLAgent : public LLOldEvents::LLObservable
 	LLHost			getRegionHost() const;
 	BOOL			inPrelude();
 
+    // Capability 
+    std::string     getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) }
+
 	/**
 	 * Register a boost callback to be called when the agent changes regions
 	 * Note that if you need to access a capability for the region, you may need to wait
@@ -631,6 +642,8 @@ class LLAgent : public LLOldEvents::LLObservable
 	void            setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange);
 
 private:
+
+
 	friend class LLTeleportRequest;
 	friend class LLTeleportRequestViaLandmark;
 	friend class LLTeleportRequestViaLure;
@@ -758,11 +771,12 @@ class LLAgent : public LLOldEvents::LLObservable
 	unsigned int                    mMaturityPreferenceNumRetries;
 	U8                              mLastKnownRequestMaturity;
 	U8                              mLastKnownResponseMaturity;
+	LLCore::HttpRequest::policy_t	mHttpPolicy;
 
 	bool            isMaturityPreferenceSyncedWithServer() const;
 	void 			sendMaturityPreferenceToServer(U8 pPreferredMaturity);
+    void            processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity);
 
-	friend class LLMaturityPreferencesResponder;
 	void            handlePreferredMaturityResult(U8 pServerMaturity);
 	void            handlePreferredMaturityError();
 	void            reportPreferredMaturitySuccess();
@@ -909,6 +923,22 @@ class LLAgent : public LLOldEvents::LLObservable
  **                                                                            **
  *******************************************************************************/
 
+/********************************************************************************
+ **                                                                            **
+ **                    UTILITY
+ **/
+public:
+    typedef LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t httpCallback_t;
+
+	/// Utilities for allowing the the agent sub managers to post and get via
+	/// HTTP using the agent's policy settings and headers.  
+    bool requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL);
+    bool requestGetCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL);
+
+/**                    Utility
+ **                                                                            **
+ *******************************************************************************/
+
 /********************************************************************************
  **                                                                            **
  **                    DEBUGGING
diff --git a/indra/newview/llagentlanguage.cpp b/indra/newview/llagentlanguage.cpp
index fe6236a32a5aaac13158ffe011d7add5e7f7a737..cdb0e3302dbafdd7fc60ec3abc3c5782636a94e3 100755
--- a/indra/newview/llagentlanguage.cpp
+++ b/indra/newview/llagentlanguage.cpp
@@ -32,6 +32,7 @@
 #include "llviewerregion.h"
 // library includes
 #include "llui.h"					// getLanguage()
+#include "httpcommon.h"
 
 // static
 void LLAgentLanguage::init()
@@ -54,22 +55,17 @@ void LLAgentLanguage::onChange()
 // static
 bool LLAgentLanguage::update()
 {
-	LLSD body;
-	std::string url;
+    LLSD body;
 
-	if (gAgent.getRegion())
-	{
-		url = gAgent.getRegion()->getCapability("UpdateAgentLanguage");
-	}
-
-	if (!url.empty())
-	{
-		std::string language = LLUI::getLanguage();
+	std::string language = LLUI::getLanguage();
 		
-		body["language"] = language;
-		body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic");
+	body["language"] = language;
+	body["language_is_public"] = gSavedSettings.getBOOL("LanguageIsPublic");
 		
-		LLHTTPClient::post(url, body, new LLHTTPClient::Responder);
-	}
+    if (!gAgent.requestPostCapability("UpdateAgentLanguage", body))
+    {
+        LL_WARNS("Language") << "Language capability unavailable." << LL_ENDL;
+    }
+
     return true;
 }
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 714b456ae72a1513ea7b678cb5fcac12bc7b4344..afc6e208e6a13cf0d64d6970bcf20e1d7be7bbd3 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -40,317 +40,381 @@
 /// Classes for AISv3 support.
 ///----------------------------------------------------------------------------
 
-// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
-AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
-	mCommandFunc(NULL),
-	mCallback(callback)
-{
-	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
-}
+//=========================================================================
+const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");
+const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3");
+
+//-------------------------------------------------------------------------
+/*static*/
+bool AISAPI::isAvailable()
+{
+    if (gAgent.getRegion())
+    {
+        return gAgent.getRegion()->isCapabilityAvailable(INVENTORY_CAP_NAME);
+    }
+    return false;
+}
+
+/*static*/
+void AISAPI::getCapNames(LLSD& capNames)
+{
+    capNames.append(INVENTORY_CAP_NAME);
+    capNames.append(LIBRARY_CAP_NAME);
+}
 
-bool AISCommand::run_command()
-{
-	if (NULL == mCommandFunc)
-	{
-		// This may happen if a command failed to initiate itself.
-		LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL;
-		return false;
-	}
-	else
-	{
-		mCommandFunc();
-		return true;
-	}
-}
+/*static*/
+std::string AISAPI::getInvCap()
+{
+    if (gAgent.getRegion())
+    {
+        return gAgent.getRegion()->getCapability(INVENTORY_CAP_NAME);
+    }
+    return std::string();
+}
+
+/*static*/
+std::string AISAPI::getLibCap()
+{
+    if (gAgent.getRegion())
+    {
+        return gAgent.getRegion()->getCapability(LIBRARY_CAP_NAME);
+    }
+    return std::string();
+}
+
+/*static*/ 
+void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback)
+{
+    std::string cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+
+    LLUUID tid;
+    tid.generate();
 
-void AISCommand::setCommandFunc(command_func_type command_func)
+    std::string url = cap + std::string("/category/") + parentId.asString() + "?tid=" + tid.asString();
+    LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+
+    // I may be suffering from golden hammer here, but the first part of this bind 
+    // is actually a static cast for &HttpCoroutineAdapter::postAndSuspend so that 
+    // the compiler can identify the correct signature to select.
+    // 
+    // Reads as follows:
+    // LLSD     - method returning LLSD
+    // (LLCoreHttpUtil::HttpCoroutineAdapter::*) - pointer to member function of HttpCoroutineAdapter
+    // (LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) - signature of method
+    //  
+    invokationFn_t postFn = boost::bind(
+        // Humans ignore next line.  It is just a cast.
+        static_cast<LLSD (LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, _4, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, postFn, url, parentId, newInventory, callback, COPYINVENTORY));
+    EnqueueAISCommand("CreateInventory", proc);
+}
+
+/*static*/ 
+void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback)
 {
-	mCommandFunc = command_func;
-}
-	
-// virtual
-bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id)
-{
-	return false;
-}
-	
-/* virtual */
-void AISCommand::httpSuccess()
-{
-	// Command func holds a reference to self, need to release it
-	// after a success or final failure.
-	setCommandFunc(no_op);
-		
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	mRetryPolicy->onSuccess();
-		
-	gInventory.onAISUpdateReceived("AISCommand", content);
+    std::string cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+
+    LLUUID tid;
+    tid.generate();
+
+    std::string url = cap + std::string("/category/") + folderId.asString() + "/links?tid=" + tid.asString();
 
-	if (mCallback)
-	{
-		LLUUID id; // will default to null if parse fails.
-		getResponseUUID(content,id);
-		mCallback->fire(id);
-	}
-}
+    // see comment above in CreateInventoryCommand
+    invokationFn_t putFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::putAndSuspend), _1, _2, _3, _4, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, putFn, url, folderId, newInventory, callback, SLAMFOLDER));
+
+    EnqueueAISCommand("SlamFolder", proc);
+}
+
+void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback)
+{
+    std::string cap;
+
+    cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+
+    std::string url = cap + std::string("/category/") + categoryId.asString();
+    LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+
+    invokationFn_t delFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, delFn, url, categoryId, LLSD(), callback, REMOVECATEGORY));
+
+    EnqueueAISCommand("RemoveCategory", proc);
+}
+
+/*static*/ 
+void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback)
+{
+    std::string cap;
+
+    cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+
+    std::string url = cap + std::string("/item/") + itemId.asString();
+    LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+
+    invokationFn_t delFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, delFn, url, itemId, LLSD(), callback, REMOVEITEM));
+
+    EnqueueAISCommand("RemoveItem", proc);
+}
+
+void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback)
+{
+    std::string cap;
+
+    cap = getLibCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Library cap not found!" << LL_ENDL;
+        return;
+    }
 
-/*virtual*/
-void AISCommand::httpFailure()
-{
-	LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
-	S32 status = getStatus();
-	const LLSD& headers = getResponseHeaders();
-	mRetryPolicy->onFailure(status, headers);
-	F32 seconds_to_wait;
-	if (mRetryPolicy->shouldRetry(seconds_to_wait))
-	{
-		doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
-	}
-	else
-	{
-		// Command func holds a reference to self, need to release it
-		// after a success or final failure.
-		// *TODO: Notify user?  This seems bad.
-		setCommandFunc(no_op);
-	}
-}
+    LL_DEBUGS("Inventory") << "Copying library category: " << sourceId << " => " << destId << LL_ENDL;
 
-//static
-bool AISCommand::isAPIAvailable()
-{
-	if (gAgent.getRegion())
-	{
-		return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3");
-	}
-	return false;
-}
+    LLUUID tid;
+    tid.generate();
 
-//static
-bool AISCommand::getInvCap(std::string& cap)
-{
-	if (gAgent.getRegion())
-	{
-		cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
-	}
-	if (!cap.empty())
-	{
-		return true;
-	}
-	return false;
-}
+    std::string url = cap + std::string("/category/") + sourceId.asString() + "?tid=" + tid.asString();
+    if (!copySubfolders)
+    {
+        url += ",depth=0";
+    }
+    LL_INFOS() << url << LL_ENDL;
 
-//static
-bool AISCommand::getLibCap(std::string& cap)
-{
-	if (gAgent.getRegion())
-	{
-		cap = gAgent.getRegion()->getCapability("LibraryAPIv3");
-	}
-	if (!cap.empty())
-	{
-		return true;
-	}
-	return false;
-}
+    std::string destination = destId.asString();
 
-//static
-void AISCommand::getCapabilityNames(LLSD& capabilityNames)
+    invokationFn_t copyFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const std::string, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::copyAndSuspend), _1, _2, _3, destination, _5, _6);
+         
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, copyFn, url, destId, LLSD(), callback, COPYLIBRARYCATEGORY));
+
+    EnqueueAISCommand("CopyLibraryCategory", proc);
+}
+
+/*static*/ 
+void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback)
 {
-	capabilityNames.append("InventoryAPIv3");
-	capabilityNames.append("LibraryAPIv3");
-}
+    std::string cap;
 
-RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
-									 LLPointer<LLInventoryCallback> callback):
-	AISCommand(callback)
-{
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	std::string url = cap + std::string("/item/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LLHTTPClient::ResponderPtr responder = this;
-	LLSD headers;
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-	setCommandFunc(cmd);
-}
+    cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
 
-RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
-											 LLPointer<LLInventoryCallback> callback):
-	AISCommand(callback)
-{
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	std::string url = cap + std::string("/category/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LLHTTPClient::ResponderPtr responder = this;
-	LLSD headers;
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-	setCommandFunc(cmd);
-}
+    std::string url = cap + std::string("/category/") + categoryId.asString() + "/children";
+    LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
 
-PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
-												 LLPointer<LLInventoryCallback> callback):
-	AISCommand(callback)
-{
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout);
-	setCommandFunc(cmd);
-}
+    invokationFn_t delFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
 
-UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
-									 const LLSD& updates,
-									 LLPointer<LLInventoryCallback> callback):
-	mUpdates(updates),
-	AISCommand(callback)
-{
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	std::string url = cap + std::string("/item/") + item_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	headers["Content-Type"] = "application/llsd+xml";
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
-	setCommandFunc(cmd);
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, delFn, url, categoryId, LLSD(), callback, PURGEDESCENDENTS));
+
+    EnqueueAISCommand("PurgeDescendents", proc);
 }
 
-UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
-											 const LLSD& updates,
-											 LLPointer<LLInventoryCallback> callback):
-	mUpdates(updates),
-	AISCommand(callback)
-{
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	std::string url = cap + std::string("/category/") + cat_id.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	headers["Content-Type"] = "application/llsd+xml";
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout);
-	setCommandFunc(cmd);
-}
 
-CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
-							 				   const LLSD& new_inventory,
-							 				   LLPointer<LLInventoryCallback> callback):
-	mNewInventory(new_inventory),
-	AISCommand(callback)
+/*static*/
+void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback)
 {
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	LLUUID tid;
-	tid.generate();
-	std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString();
-	LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	headers["Content-Type"] = "application/llsd+xml";
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder, headers, timeout);
-	setCommandFunc(cmd);
+    std::string cap;
+
+    cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+    std::string url = cap + std::string("/category/") + categoryId.asString();
+
+    invokationFn_t patchFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndSuspend), _1, _2, _3, _4, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, patchFn, url, categoryId, updates, callback, UPDATECATEGORY));
+
+    EnqueueAISCommand("UpdateCategory", proc);
 }
 
-SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
-	mContents(contents),
-	AISCommand(callback)
+/*static*/
+void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback)
 {
-	std::string cap;
-	if (!getInvCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	LLUUID tid;
-	tid.generate();
-	std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
-	LL_INFOS() << url << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	headers["Content-Type"] = "application/llsd+xml";
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout);
-	setCommandFunc(cmd);
+
+    std::string cap;
+
+    cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        return;
+    }
+    std::string url = cap + std::string("/item/") + itemId.asString();
+
+    invokationFn_t patchFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body 
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndSuspend), _1, _2, _3, _4, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
+        _1, patchFn, url, itemId, updates, callback, UPDATEITEM));
+
+    EnqueueAISCommand("UpdateItem", proc);
 }
 
-CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
-													   const LLUUID& dest_id,
-													   LLPointer<LLInventoryCallback> callback,
-													   bool copy_subfolders):
-	AISCommand(callback)
+/*static*/
+void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc)
 {
-	std::string cap;
-	if (!getLibCap(cap))
-	{
-		LL_WARNS() << "No cap found" << LL_ENDL;
-		return;
-	}
-	LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
-	LLUUID tid;
-	tid.generate();
-	std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
-	if (!copy_subfolders)
-	{
-		url += ",depth=0";
-	}
-	LL_INFOS() << url << LL_ENDL;
-	LLCurl::ResponderPtr responder = this;
-	LLSD headers;
-	F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder, headers, timeout);
-	setCommandFunc(cmd);
+    std::string procFullName = "AIS(" + procName + ")";
+    LLCoprocedureManager::instance().enqueueCoprocedure("AIS", procFullName, proc);
+
 }
 
-bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id)
+/*static*/
+void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter, 
+        invokationFn_t invoke, std::string url, 
+        LLUUID targetId, LLSD body, completion_t callback, COMMAND_TYPE type)
 {
-	if (content.has("category_id"))
-	{
-		id = content["category_id"];
-		return true;
-	}
-	return false;
+    LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+    LLCore::HttpHeaders::ptr_t httpHeaders;
+
+    httpOptions->setTimeout(LLCoreHttpUtil::HTTP_REQUEST_EXPIRY_SECS);
+
+    LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
+
+    LLSD result = invoke(httpAdapter, httpRequest, url, body, httpOptions, httpHeaders);
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status || !result.isMap())
+    {
+        if (!result.isMap())
+        {
+            status = LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents");
+        }
+        LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL;
+        LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL;
+    }
+
+    gInventory.onAISUpdateReceived("AISCommand", result);
+
+    if (callback && !callback.empty())
+    {   
+        LLUUID id(LLUUID::null);
+
+        if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
+	    {
+		    id = result["category_id"];
+	    }
+
+        callback(id);
+    }
+
 }
 
+//-------------------------------------------------------------------------
 AISUpdate::AISUpdate(const LLSD& update)
 {
 	parseUpdate(update);
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index bb483fb1335fac2606b5ac4f5d96041308d9a35e..e97059014bd11fedf3847eb78041544de3d78cf9 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -31,112 +31,55 @@
 #include <map>
 #include <set>
 #include <string>
-#include "llcurl.h"
-#include "llhttpclient.h"
 #include "llhttpretrypolicy.h"
 #include "llviewerinventory.h"
+#include "llcorehttputil.h"
+#include "llcoproceduremanager.h"
 
-class AISCommand: public LLHTTPClient::Responder
+class AISAPI
 {
 public:
-	typedef boost::function<void()> command_func_type;
+    typedef boost::function<void(const LLUUID &invItem)>    completion_t;
 
-	AISCommand(LLPointer<LLInventoryCallback> callback);
+    static bool isAvailable();
+    static void getCapNames(LLSD& capNames);
 
-	virtual ~AISCommand() {}
+    static void CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback = completion_t());
+    static void SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback = completion_t());
+    static void RemoveCategory(const LLUUID &categoryId, completion_t callback = completion_t());
+    static void RemoveItem(const LLUUID &itemId, completion_t callback = completion_t());
+    static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t());
+    static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t());
+    static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t());
+    static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
 
-	bool run_command();
-
-	void setCommandFunc(command_func_type command_func);
-	
-	// Need to do command-specific parsing to get an id here, for
-	// LLInventoryCallback::fire().  May or may not need to bother,
-	// since most LLInventoryCallbacks do their work in the
-	// destructor.
-	
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-
-	static bool isAPIAvailable();
-	static bool getInvCap(std::string& cap);
-	static bool getLibCap(std::string& cap);
-	static void getCapabilityNames(LLSD& capabilityNames);
-
-protected:
-	virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
-
-private:
-	command_func_type mCommandFunc;
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-	LLPointer<LLInventoryCallback> mCallback;
-};
-
-class RemoveItemCommand: public AISCommand
-{
-public:
-	RemoveItemCommand(const LLUUID& item_id,
-					  LLPointer<LLInventoryCallback> callback);
-};
-
-class RemoveCategoryCommand: public AISCommand
-{
-public:
-	RemoveCategoryCommand(const LLUUID& item_id,
-						  LLPointer<LLInventoryCallback> callback);
-};
-
-class PurgeDescendentsCommand: public AISCommand
-{
-public:
-	PurgeDescendentsCommand(const LLUUID& item_id,
-							LLPointer<LLInventoryCallback> callback);
-};
-
-class UpdateItemCommand: public AISCommand
-{
-public:
-	UpdateItemCommand(const LLUUID& item_id,
-					  const LLSD& updates,
-					  LLPointer<LLInventoryCallback> callback);
 private:
-	LLSD mUpdates;
-};
+    typedef enum {
+        COPYINVENTORY,
+        SLAMFOLDER,
+        REMOVECATEGORY,
+        REMOVEITEM,
+        PURGEDESCENDENTS,
+        UPDATECATEGORY,
+        UPDATEITEM,
+        COPYLIBRARYCATEGORY
+    } COMMAND_TYPE;
 
-class UpdateCategoryCommand: public AISCommand
-{
-public:
-	UpdateCategoryCommand(const LLUUID& cat_id,
-						  const LLSD& updates,
-						  LLPointer<LLInventoryCallback> callback);
-private:
-	LLSD mUpdates;
-};
+    static const std::string INVENTORY_CAP_NAME;
+    static const std::string LIBRARY_CAP_NAME;
 
-class SlamFolderCommand: public AISCommand
-{
-public:
-	SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback);
-	
-private:
-	LLSD mContents;
-};
+    typedef boost::function < LLSD (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t, LLCore::HttpRequest::ptr_t,
+        const std::string, LLSD, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) > invokationFn_t;
 
-class CopyLibraryCategoryCommand: public AISCommand
-{
-public:
-	CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback, bool copy_subfolders = true);
+    static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc);
 
-protected:
-	/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
-};
+    static std::string getInvCap();
+    static std::string getLibCap();
 
-class CreateInventoryCommand: public AISCommand
-{
-public:
-	CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer<LLInventoryCallback> callback);
+    static void InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter, 
+        invokationFn_t invoke, std::string url, LLUUID targetId, LLSD body, 
+        completion_t callback, COMMAND_TYPE type);
 
-private:
-	LLSD mNewInventory;
 };
 
 class AISUpdate
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index f5f224b83ed8295aedc23375f701b216c4be9952..91a5148e4ceb22a91f68e4d8385c7d56dcad85d7 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -31,6 +31,10 @@
 #include "llappviewer.h"
 #include "llviewercontrol.h"
 
+#include <openssl/x509_vfy.h>
+#include <openssl/ssl.h>
+#include "llsecapi.h"
+#include <curl/curl.h>
 
 // Here is where we begin to get our connection usage under control.
 // This establishes llcorehttp policy classes that, among other
@@ -93,6 +97,16 @@ static const struct
 		4,		1,		4,		0,		false,
 		"",
 		"inventory"
+	},
+	{ // AP_MATERIALS
+		2,		1,		8,		0,		false,
+		"RenderMaterials",
+		"material manager requests"
+	},
+	{ // AP_AGENT
+		2,		1,		32,		0,		true,
+		"Agent",
+		"Agent requests"
 	}
 };
 
@@ -124,6 +138,9 @@ LLAppCoreHttp::~LLAppCoreHttp()
 
 void LLAppCoreHttp::init()
 {
+
+    LLCore::LLHttp::initialize();
+
 	LLCore::HttpStatus status = LLCore::HttpRequest::createService();
 	if (! status)
 	{
@@ -151,6 +168,15 @@ void LLAppCoreHttp::init()
 						 << LL_ENDL;
 	}
 
+	// Set up SSL Verification call back.
+	status = LLCore::HttpRequest::setStaticPolicyOption(LLCore::HttpRequest::PO_SSL_VERIFY_CALLBACK,
+														LLCore::HttpRequest::GLOBAL_POLICY_ID,
+														sslVerify, NULL);
+	if (!status)
+	{
+		LL_WARNS("Init") << "Failed to set SSL Verification.  Reason:  " << status.toString() << LL_ENDL;
+	}
+
 	// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):
 	// 0 - None
 	// 1 - Basic start, stop simple transitions
@@ -182,6 +208,8 @@ void LLAppCoreHttp::init()
 		}
 
 		mHttpClasses[app_policy].mPolicy = LLCore::HttpRequest::createPolicyClass();
+		// We have run out of available HTTP policies. Adjust HTTP_POLICY_CLASS_LIMIT in _httpinternal.h
+		llassert(mHttpClasses[app_policy].mPolicy != LLCore::HttpRequest::INVALID_POLICY_ID);
 		if (! mHttpClasses[app_policy].mPolicy)
 		{
 			// Use default policy (but don't accidentally modify default)
@@ -457,6 +485,62 @@ void LLAppCoreHttp::refreshSettings(bool initial)
 	}
 }
 
+LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, 
+	LLCore::HttpHandler const * const handler, void *appdata)
+{
+	X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
+	LLCore::HttpStatus result;
+	LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
+	LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
+	LLSD validation_params = LLSD::emptyMap();
+	LLURI uri(url);
+
+	validation_params[CERT_HOSTNAME] = uri.hostName();
+
+	// *TODO: In the case of an exception while validating the cert, we need a way
+	// to pass the offending(?) cert back out. *Rider*
+
+	try
+	{
+		// don't validate hostname.  Let libcurl do it instead.  That way, it'll handle redirects
+		store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
+	}
+	catch (LLCertValidationTrustException &cert_exception)
+	{
+		// this exception is is handled differently than the general cert
+		// exceptions, as we allow the user to actually add the certificate
+		// for trust.
+		// therefore we pass back a different error code
+		// NOTE: We're currently 'wired' to pass around CURL error codes.  This is
+		// somewhat clumsy, as we may run into errors that do not map directly to curl
+		// error codes.  Should be refactored with login refactoring, perhaps.
+		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
+		result.setMessage(cert_exception.getMessage());
+		LLPointer<LLCertificate> cert = cert_exception.getCert();
+		cert->ref(); // adding an extra ref here
+		result.setErrorData(cert.get());
+		// We should probably have a more generic way of passing information
+		// back to the error handlers.
+	}
+	catch (LLCertException &cert_exception)
+	{
+		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
+		result.setMessage(cert_exception.getMessage());
+		LLPointer<LLCertificate> cert = cert_exception.getCert();
+		cert->ref(); // adding an extra ref here
+		result.setErrorData(cert.get());
+	}
+	catch (...)
+	{
+		// any other odd error, we just handle as a connect error.
+		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CONNECT_ERROR);
+	}
+
+	return result;
+}
+
+
+
 
 void LLAppCoreHttp::onCompleted(LLCore::HttpHandle, LLCore::HttpResponse *)
 {
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index 37d7a737e774bb4124145b489b838cdc04690edc..410d7c6b0796ae0dedce981f7ac44e60f38790e9 100755
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -164,7 +164,29 @@ class LLAppCoreHttp : public LLCore::HttpHandler
 		/// Pipelined:       no
 		AP_INVENTORY,
 		AP_REPORTING = AP_INVENTORY,	// Piggy-back on inventory
-		
+
+		/// Material resource requests and puts.  
+		///
+		/// Destination:     simhost:12043
+		/// Protocol:        https:
+		/// Transfer size:   KB
+		/// Long poll:       no
+		/// Concurrency:     low
+		/// Request rate:    low
+		/// Pipelined:       no
+		AP_MATERIALS,
+
+		/// Appearance resource requests and puts.  
+		///
+		/// Destination:     simhost:12043
+		/// Protocol:        https:
+		/// Transfer size:   KB
+		/// Long poll:       no
+		/// Concurrency:     mid
+		/// Request rate:    low
+		/// Pipelined:       yes
+		AP_AGENT,
+
 		AP_COUNT						// Must be last
 	};
 	
@@ -233,7 +255,9 @@ class LLAppCoreHttp : public LLCore::HttpHandler
 	bool						mStopped;
 	HttpClass					mHttpClasses[AP_COUNT];
 	bool						mPipelined;				// Global setting
-	boost::signals2::connection mPipelinedSignal;		// Signal for 'HttpPipelining' setting
+	boost::signals2::connection	mPipelinedSignal;		// Signal for 'HttpPipelining' setting
+
+	static LLCore::HttpStatus	sslVerify(const std::string &uri, LLCore::HttpHandler const * const handler, void *appdata);
 };
 
 
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 35593dd4ff29516d62c7a7a816601d4a1db2ff2f..eea585e9982385c4e9376b970c1da80613201ef6 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -23,7 +23,7 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
-
+ 
 #include "llviewerprecompiledheaders.h"
 
 #include <boost/lexical_cast.hpp>
@@ -54,12 +54,26 @@
 #include "llsdserialize.h"
 #include "llhttpretrypolicy.h"
 #include "llaisapi.h"
+#include "llhttpsdhandler.h"
+#include "llcorehttputil.h"
+#include "llappviewer.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
 #pragma warning (disable:4702)
 #endif
 
+#if 1
+// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model.
+// temp code in transition
+void doAppearanceCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
+{
+    if (cb.notNull())
+        cb->fire(id);
+}
+#endif
+
+
 std::string self_av_string()
 {
 	// On logout gAgentAvatarp can already be invalid
@@ -1257,6 +1271,8 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
 	items = new_items;
 }
 
+//=========================================================================
+
 const LLUUID LLAppearanceMgr::getCOF() const
 {
 	return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
@@ -2458,8 +2474,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 			 << " )" << LL_ENDL;
 
 	// If we are copying from library, attempt to use AIS to copy the category.
-	bool ais_ran=false;
-	if (copy && AISCommand::isAPIAvailable())
+    if (copy && AISAPI::isAvailable())
 	{
 		LLUUID parent_id;
 		parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
@@ -2471,11 +2486,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 		LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append);
 		LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper(
 													std::string("wear_inventory_category_callback"), copy_cb);
-		LLPointer<AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb, false);
-		ais_ran=cmd_ptr->run_command();
-	}
 
-	if (!ais_ran)
+        AISAPI::completion_t cr = boost::bind(&doAppearanceCb, track_cb, _1);
+        AISAPI::CopyLibraryCategory(category->getUUID(), parent_id, false, cr);
+	}
+    else
 	{
 		selfStartPhase("wear_inventory_category_fetch");
 		callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
@@ -3267,276 +3282,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
 		
 }
 
-class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(RequestAgentUpdateAppearanceResponder);
-
-	friend class LLAppearanceMgr;
-	
-public:
-	RequestAgentUpdateAppearanceResponder();
-
-	virtual ~RequestAgentUpdateAppearanceResponder();
-
-private:
-	// Called when sendServerAppearanceUpdate called. May or may not
-	// trigger a request depending on various bits of state.
-	void onRequestRequested();
-
-	// Post the actual appearance request to cap.
-	void sendRequest();
-
-	void debugCOF(const LLSD& content);
-
-protected:
-	// Successful completion.
-	/* virtual */ void httpSuccess();
-
-	// Error
-	/*virtual*/ void httpFailure();
-
-	void onFailure();
-	void onSuccess();
-
-	S32 mInFlightCounter;
-	LLTimer mInFlightTimer;
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
-
-RequestAgentUpdateAppearanceResponder::RequestAgentUpdateAppearanceResponder()
-{
-	bool retry_on_4xx = true;
-	mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10, retry_on_4xx);
-	mInFlightCounter = 0;
-}
-
-RequestAgentUpdateAppearanceResponder::~RequestAgentUpdateAppearanceResponder()
-{
-}
-
-void RequestAgentUpdateAppearanceResponder::onRequestRequested()
-{
-	// If we have already received an update for this or higher cof version, ignore.
-	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
-	S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
-	S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
-	LL_DEBUGS("Avatar") << "cof_version " << cof_version
-						<< " last_rcv " << last_rcv
-						<< " last_req " << last_req
-						<< " in flight " << mInFlightCounter << LL_ENDL;
-	if ((mInFlightCounter>0) && (mInFlightTimer.hasExpired()))
-	{
-		LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
-		mInFlightCounter = 0;
-	}
-	if (cof_version < last_rcv)
-	{
-		LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
-							<< " will not request for " << cof_version << LL_ENDL;
-		return;
-	}
-	if (mInFlightCounter>0 && last_req >= cof_version)
-	{
-		LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req 
-							<< " will not request for " << cof_version << LL_ENDL;
-		return;
-	}
-
-	// Actually send the request.
-	LL_DEBUGS("Avatar") << "ATT sending bake request for cof_version " << cof_version << LL_ENDL;
-	mRetryPolicy->reset();
-	sendRequest();
-}
-	
-void RequestAgentUpdateAppearanceResponder::sendRequest()
-{
-	if (gAgentAvatarp->isEditingAppearance()) 
-	{
-		// don't send out appearance updates if in appearance editing mode
-		return;
-	}
-
-	if (!gAgent.getRegion())
-	{
-		LL_WARNS() << "Region not set, cannot request server appearance update" << LL_ENDL;
-		return;
-	}
-	if (gAgent.getRegion()->getCentralBakeVersion()==0)
-	{
-		LL_WARNS() << "Region does not support baking" << LL_ENDL;
-	}
-	std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");	
-	if (url.empty())
-	{
-		LL_WARNS() << "No cap for UpdateAvatarAppearance." << LL_ENDL;
-		return;
-	}
-	
-	LLSD body;
-	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
-	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
-	{
-		body = LLAppearanceMgr::instance().dumpCOF();
-	}
-	else
-	{
-		body["cof_version"] = cof_version;
-		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
-		{
-			body["cof_version"] = cof_version+999;
-		}
-	}
-	LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << LL_ENDL;
-
-	mInFlightCounter++;
-	mInFlightTimer.setTimerExpirySec(60.0);
-	LLHTTPClient::post(url, body, this);
-	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
-	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
-}
-
-void RequestAgentUpdateAppearanceResponder::debugCOF(const LLSD& content)
-{
-	LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
-					   << " ================================= " << LL_ENDL;
-	std::set<LLUUID> ais_items, local_items;
-	const LLSD& cof_raw = content["cof_raw"];
-	for (LLSD::array_const_iterator it = cof_raw.beginArray();
-		 it != cof_raw.endArray(); ++it)
-	{
-		const LLSD& item = *it;
-		if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
-		{
-			ais_items.insert(item["item_id"].asUUID());
-			if (item["type"].asInteger() == 24) // link
-			{
-				LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
-								   << " linked_item_id: " << item["asset_id"].asUUID()
-								   << " name: " << item["name"].asString()
-								   << LL_ENDL; 
-			}
-			else if (item["type"].asInteger() == 25) // folder link
-			{
-				LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
-								   << " linked_item_id: " << item["asset_id"].asUUID()
-								   << " name: " << item["name"].asString()
-								   << LL_ENDL; 
-			}
-			else
-			{
-				LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
-								   << " linked_item_id: " << item["asset_id"].asUUID()
-								   << " name: " << item["name"].asString()
-								   << " type: " << item["type"].asInteger()
-								   << LL_ENDL; 
-			}
-		}
-	}
-	LL_INFOS("Avatar") << LL_ENDL;
-	LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger() 
-					   << " ================================= " << LL_ENDL;
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t item_array;
-	gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
-								  cat_array,item_array,LLInventoryModel::EXCLUDE_TRASH);
-	for (S32 i=0; i<item_array.size(); i++)
-	{
-		const LLViewerInventoryItem* inv_item = item_array.at(i).get();
-		local_items.insert(inv_item->getUUID());
-		LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
-						   << " linked_item_id: " << inv_item->getLinkedUUID()
-						   << " name: " << inv_item->getName()
-						   << " parent: " << inv_item->getParentUUID()
-						   << LL_ENDL;
-	}
-	LL_INFOS("Avatar") << " ================================= " << LL_ENDL;
-	S32 local_only = 0, ais_only = 0;
-	for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
-	{
-		if (ais_items.find(*it) == ais_items.end())
-		{
-			LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL;
-			local_only++;
-		}
-	}
-	for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
-	{
-		if (local_items.find(*it) == local_items.end())
-		{
-			LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL;
-			ais_only++;
-		}
-	}
-	if (local_only==0 && ais_only==0)
-	{
-		LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
-						   << content["observed"].asInteger()
-						   << " rcv " << content["expected"].asInteger()
-						   << ")" << LL_ENDL;
-	}
-}
-
-/* virtual */ void RequestAgentUpdateAppearanceResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	if (content["success"].asBoolean())
-	{
-		LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
-		if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-		{
-			dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", content);
-		}
-
-		onSuccess();
-	}
-	else
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content);
-	}
-}
-
-void RequestAgentUpdateAppearanceResponder::onSuccess()
-{
-	mInFlightCounter = llmax(mInFlightCounter-1,0);
-}
-
-/*virtual*/ void RequestAgentUpdateAppearanceResponder::httpFailure()
-{
-	LL_WARNS("Avatar") << "appearance update request failed, status "
-					   << getStatus() << " reason " << getReason() << LL_ENDL;
-
-	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
-	{
-		const LLSD& content = getContent();
-		dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
-		debugCOF(content);
-	}
-	onFailure();
-}
-
-void RequestAgentUpdateAppearanceResponder::onFailure()
-{
-	mInFlightCounter = llmax(mInFlightCounter-1,0);
-
-	F32 seconds_to_wait;
-	mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
-	if (mRetryPolicy->shouldRetry(seconds_to_wait))
-	{
-		LL_INFOS() << "retrying" << LL_ENDL;
-		doAfterInterval(boost::bind(&RequestAgentUpdateAppearanceResponder::sendRequest,this),
-						seconds_to_wait);
-	}
-	else
-	{
-		LL_WARNS() << "giving up after too many retries" << LL_ENDL;
-	}
-}	
-
 
 LLSD LLAppearanceMgr::dumpCOF() const
 {
@@ -3603,102 +3348,201 @@ LLSD LLAppearanceMgr::dumpCOF() const
 
 void LLAppearanceMgr::requestServerAppearanceUpdate()
 {
-	mAppearanceResponder->onRequestRequested();
-}
 
-class LLIncrementCofVersionResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLIncrementCofVersionResponder);
-public:
-	LLIncrementCofVersionResponder() : LLHTTPClient::Responder()
+	if (!testCOFRequestVersion())
 	{
-		mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 16.0, 2.0, 5);
+		// *TODO: LL_LOG message here
+		return;
 	}
 
-	virtual ~LLIncrementCofVersionResponder()
+	if ((mInFlightCounter > 0) && (mInFlightTimer.hasExpired()))
 	{
+		LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
+		mInFlightCounter = 0;
 	}
 
-protected:
-	virtual void httpSuccess()
+	if (gAgentAvatarp->isEditingAppearance())
 	{
-		LL_INFOS() << "Successfully incremented agent's COF." << LL_ENDL;
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		S32 new_version = content["category"]["version"].asInteger();
-
-		// cof_version should have increased
-		llassert(new_version > gAgentAvatarp->mLastUpdateRequestCOFVersion);
-
-		gAgentAvatarp->mLastUpdateRequestCOFVersion = new_version;
+		LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL;
+		// don't send out appearance updates if in appearance editing mode
+		return;
 	}
 
-	virtual void httpFailure()
+	if (!gAgent.getRegion())
 	{
-		LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error "
-						   << dumpResponse() << LL_ENDL;
-		F32 seconds_to_wait;
-		mRetryPolicy->onFailure(getStatus(), getResponseHeaders());
-		if (mRetryPolicy->shouldRetry(seconds_to_wait))
-		{
-			LL_INFOS() << "retrying" << LL_ENDL;
-			doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion,
-										LLAppearanceMgr::getInstance(),
-										LLHTTPClient::ResponderPtr(this)),
-										seconds_to_wait);
-		}
-		else
-		{
-			LL_WARNS() << "giving up after too many retries" << LL_ENDL;
-		}
+		LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL;
+		return;
 	}
-
-private:
-	LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
-};
-
-void LLAppearanceMgr::incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr)
-{
-	// If we don't have a region, report it as an error
-	if (gAgent.getRegion() == NULL)
+	if (gAgent.getRegion()->getCentralBakeVersion() == 0)
 	{
-		LL_WARNS() << "Region not set, cannot request cof_version increment" << LL_ENDL;
-		return;
+		LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL;
 	}
 
-	std::string url = gAgent.getRegion()->getCapability("IncrementCofVersion");
-	if (url.empty())
+	LLSD postData;
+	S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
+	if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
 	{
-		LL_WARNS() << "No cap for IncrementCofVersion." << LL_ENDL;
-		return;
+		postData = LLAppearanceMgr::instance().dumpCOF();
 	}
-
-	LL_INFOS() << "Requesting cof_version be incremented via capability to: "
-			<< url << LL_ENDL;
-	LLSD headers;
-	LLSD body = LLSD::emptyMap();
-
-	if (!responder_ptr.get())
+	else
 	{
-		responder_ptr = LLHTTPClient::ResponderPtr(new LLIncrementCofVersionResponder());
+		postData["cof_version"] = cof_version;
+		if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
+		{
+			postData["cof_version"] = cof_version + 999;
+		}
 	}
 
-	LLHTTPClient::get(url, body, responder_ptr, headers, 30.0f);
+	mInFlightCounter++;
+	mInFlightTimer.setTimerExpirySec(60.0);
+
+	llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
+	gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+
+    if (!gAgent.requestPostCapability("UpdateAvatarAppearance", postData, 
+        static_cast<LLAgent::httpCallback_t>(boost::bind(&LLAppearanceMgr::serverAppearanceUpdateSuccess, this, _1)), 
+        static_cast<LLAgent::httpCallback_t>(boost::bind(&LLAppearanceMgr::decrementInFlightCounter, this))))
+    {
+        LL_WARNS("Avatar") << "Unable to access UpdateAvatarAppearance in this region." << LL_ENDL;
+    }
 }
 
-U32 LLAppearanceMgr::getNumAttachmentsInCOF()
+void LLAppearanceMgr::serverAppearanceUpdateSuccess(const LLSD &result)
 {
-	const LLUUID cof = getCOF();
-	LLInventoryModel::item_array_t obj_items;
-	getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT);
-	return obj_items.size();
+    decrementInFlightCounter();
+    if (result["success"].asBoolean())
+    {
+        LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
+        if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+        {
+            dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result);
+        }
+    }
+    else
+    {
+        LL_WARNS("Avatar") << "Non success response for change appearance" << LL_ENDL;
+        if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+        {
+            debugAppearanceUpdateCOF(result);
+        }
+    }
+}
+
+/*static*/
+void LLAppearanceMgr::debugAppearanceUpdateCOF(const LLSD& content)
+{
+    dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content);
+
+    LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
+        << " ================================= " << LL_ENDL;
+    std::set<LLUUID> ais_items, local_items;
+    const LLSD& cof_raw = content["cof_raw"];
+    for (LLSD::array_const_iterator it = cof_raw.beginArray();
+        it != cof_raw.endArray(); ++it)
+    {
+        const LLSD& item = *it;
+        if (item["parent_id"].asUUID() == LLAppearanceMgr::instance().getCOF())
+        {
+            ais_items.insert(item["item_id"].asUUID());
+            if (item["type"].asInteger() == 24) // link
+            {
+                LL_INFOS("Avatar") << "AIS Link: item_id: " << item["item_id"].asUUID()
+                    << " linked_item_id: " << item["asset_id"].asUUID()
+                    << " name: " << item["name"].asString()
+                    << LL_ENDL;
+            }
+            else if (item["type"].asInteger() == 25) // folder link
+            {
+                LL_INFOS("Avatar") << "AIS Folder link: item_id: " << item["item_id"].asUUID()
+                    << " linked_item_id: " << item["asset_id"].asUUID()
+                    << " name: " << item["name"].asString()
+                    << LL_ENDL;
+            }
+            else
+            {
+                LL_INFOS("Avatar") << "AIS Other: item_id: " << item["item_id"].asUUID()
+                    << " linked_item_id: " << item["asset_id"].asUUID()
+                    << " name: " << item["name"].asString()
+                    << " type: " << item["type"].asInteger()
+                    << LL_ENDL;
+            }
+        }
+    }
+    LL_INFOS("Avatar") << LL_ENDL;
+    LL_INFOS("Avatar") << "Local COF, version requested: " << content["observed"].asInteger()
+        << " ================================= " << LL_ENDL;
+    LLInventoryModel::cat_array_t cat_array;
+    LLInventoryModel::item_array_t item_array;
+    gInventory.collectDescendents(LLAppearanceMgr::instance().getCOF(),
+        cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH);
+    for (S32 i = 0; i < item_array.size(); i++)
+    {
+        const LLViewerInventoryItem* inv_item = item_array.at(i).get();
+        local_items.insert(inv_item->getUUID());
+        LL_INFOS("Avatar") << "LOCAL: item_id: " << inv_item->getUUID()
+            << " linked_item_id: " << inv_item->getLinkedUUID()
+            << " name: " << inv_item->getName()
+            << " parent: " << inv_item->getParentUUID()
+            << LL_ENDL;
+    }
+    LL_INFOS("Avatar") << " ================================= " << LL_ENDL;
+    S32 local_only = 0, ais_only = 0;
+    for (std::set<LLUUID>::iterator it = local_items.begin(); it != local_items.end(); ++it)
+    {
+        if (ais_items.find(*it) == ais_items.end())
+        {
+            LL_INFOS("Avatar") << "LOCAL ONLY: " << *it << LL_ENDL;
+            local_only++;
+        }
+    }
+    for (std::set<LLUUID>::iterator it = ais_items.begin(); it != ais_items.end(); ++it)
+    {
+        if (local_items.find(*it) == local_items.end())
+        {
+            LL_INFOS("Avatar") << "AIS ONLY: " << *it << LL_ENDL;
+            ais_only++;
+        }
+    }
+    if (local_only == 0 && ais_only == 0)
+    {
+        LL_INFOS("Avatar") << "COF contents identical, only version numbers differ (req "
+            << content["observed"].asInteger()
+            << " rcv " << content["expected"].asInteger()
+            << ")" << LL_ENDL;
+    }
 }
 
 
+bool LLAppearanceMgr::testCOFRequestVersion() const
+{
+	// If we have already received an update for this or higher cof version, ignore.
+	S32 cof_version = getCOFVersion();
+	S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
+	S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
+
+	LL_DEBUGS("Avatar") << "cof_version " << cof_version
+		<< " last_rcv " << last_rcv
+		<< " last_req " << last_req
+		<< " in flight " << mInFlightCounter 
+		<< LL_ENDL;
+	if (cof_version < last_rcv)
+	{
+		LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
+			<< " will not request for " << cof_version << LL_ENDL;
+		return false;
+	}
+	if (/*mInFlightCounter > 0 &&*/ last_req >= cof_version)
+	{
+		LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req
+			<< " will not request for " << cof_version << LL_ENDL;
+		return false;
+	}
+
+	// Actually send the request.
+	LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
+	return true;
+}
+
 std::string LLAppearanceMgr::getAppearanceServiceURL() const
 {
 	if (gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride").empty())
@@ -3774,7 +3618,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
 
 	// First, make a folder in the My Outfits directory.
 	const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
-	if (AISCommand::isAPIAvailable())
+    if (AISAPI::isAvailable())
 	{
 		// cap-based category creation was buggy until recently. use
 		// existence of AIS as an indicator the fix is present. Does
@@ -3967,15 +3811,17 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
 	}
 }
 
+bool LLAppearanceMgr::mActive = true;
+
 LLAppearanceMgr::LLAppearanceMgr():
 	mAttachmentInvLinkEnabled(false),
 	mOutfitIsDirty(false),
 	mOutfitLocked(false),
-	mIsInUpdateAppearanceFromCOF(false),
-	mAppearanceResponder(new RequestAgentUpdateAppearanceResponder)
+	mInFlightCounter(0),
+	mInFlightTimer(),
+	mIsInUpdateAppearanceFromCOF(false)
 {
 	LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
-
 	// unlock outfit on save operation completed
 	outfit_observer.addCOFSavedCallback(boost::bind(
 			&LLAppearanceMgr::setOutfitLocked, this, false));
@@ -3983,11 +3829,12 @@ LLAppearanceMgr::LLAppearanceMgr():
 	mUnlockOutfitTimer.reset(new LLOutfitUnLockTimer(gSavedSettings.getS32(
 			"OutfitOperationsTimeout")));
 
-	gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle,NULL);
+	gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle, NULL);
 }
 
 LLAppearanceMgr::~LLAppearanceMgr()
 {
+	mActive = false;
 }
 
 void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 4ed8c1bfb912c3caa1ed2f8bbe4f7e055a563bb4..9b6ceb7d3edbfd66884ff4fbcc18a096a329c68f 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -34,12 +34,10 @@
 #include "llinventorymodel.h"
 #include "llinventoryobserver.h"
 #include "llviewerinventory.h"
-#include "llhttpclient.h"
 
 class LLWearableHoldingPattern;
 class LLInventoryCallback;
 class LLOutfitUnLockTimer;
-class RequestAgentUpdateAppearanceResponder;
 
 class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 {
@@ -54,7 +52,6 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void updateAppearanceFromCOF(bool enforce_item_restrictions = true,
 								 bool enforce_ordering = true,
 								 nullary_func_t post_update_func = no_op);
-	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
 	void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
@@ -224,20 +221,23 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 
 	void requestServerAppearanceUpdate();
 
-	void incrementCofVersion(LLHTTPClient::ResponderPtr responder_ptr = NULL);
+	void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
+	std::string getAppearanceServiceURL() const;
 
-	U32 getNumAttachmentsInCOF();
 
-	// *HACK Remove this after server side texture baking is deployed on all sims.
-	void incrementCofVersionLegacy();
+	bool testCOFRequestVersion() const;
+	void decrementInFlightCounter()
+	{
+		mInFlightCounter = llmax(mInFlightCounter - 1, 0);
+	}
 
-	void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; }
-	std::string getAppearanceServiceURL() const;
 
 private:
+    void serverAppearanceUpdateSuccess(const LLSD &result);
+    static void debugAppearanceUpdateCOF(const LLSD& content);
+
 	std::string		mAppearanceServiceURL;
 	
-
 protected:
 	LLAppearanceMgr();
 	~LLAppearanceMgr();
@@ -261,13 +261,14 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	bool mOutfitIsDirty;
 	bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls.
 
-	LLPointer<RequestAgentUpdateAppearanceResponder> mAppearanceResponder;
-
 	/**
 	 * Lock for blocking operations on outfit until server reply or timeout exceed
 	 * to avoid unsynchronized outfit state or performing duplicate operations.
 	 */
 	bool mOutfitLocked;
+	S32  mInFlightCounter;
+	LLTimer mInFlightTimer;
+	static bool mActive;
 
 	std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer;
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9b9b591cd14d92f4fe5c9702d3e0dfe8565435a7..44c9f893b8e916e0fa961e13c97c1d245e8322af 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -57,8 +57,6 @@
 #include "llfocusmgr.h"
 #include "llviewerjoystick.h"
 #include "llallocator.h"
-#include "llares.h" 
-#include "llcurl.h"
 #include "llcalc.h"
 #include "llconversationlog.h"
 #include "lldxhardware.h"
@@ -228,7 +226,7 @@
 #include "llmachineid.h"
 #include "llmainlooprepeater.h"
 
-
+#include "llcoproceduremanager.h"
 #include "llviewereventrecorder.h"
 
 
@@ -755,8 +753,11 @@ void fast_exit(int rc)
 {
 	_exit(rc);
 }
+
+
 }
 
+
 bool LLAppViewer::init()
 {	
 	setupErrorHandling(mSecondInstance);
@@ -825,12 +826,7 @@ bool LLAppViewer::init()
 	// before consumers (LLTextureFetch).
 	mAppCoreHttp.init();
 	
-    // *NOTE:Mani - LLCurl::initClass is not thread safe. 
-    // Called before threads are created.
-    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), 
-						gSavedSettings.getS32("CurlMaximumNumberOfHandles"), 
-						gSavedSettings.getBOOL("CurlUseMultipleThreads"));
-	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
+	LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ;
 
     LLMachineID::init();
 	
@@ -900,7 +896,7 @@ bool LLAppViewer::init()
 	// the libs involved in getting to a full login screen.
 	//
 	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
-	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
+	LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL;
 
 	/////////////////////////////////////////////////
 	// OS-specific login dialogs
@@ -1157,8 +1153,6 @@ bool LLAppViewer::init()
 	{
 	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
 	}
-	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
-
 
 	gGLActive = FALSE;
 
@@ -1216,6 +1210,12 @@ bool LLAppViewer::init()
 
 	LLAgentLanguage::init();
 
+    /// Tell the Coprocedure manager how to discover and store the pool sizes
+    // what I wanted
+    LLCoprocedureManager::getInstance()->setPropertyMethods(
+        boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),
+        boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS));
+
 	return true;
 }
 
@@ -1282,7 +1282,6 @@ static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
 static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
 static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
 static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump");
-static LLTrace::BlockTimerStatHandle FTM_PUMP_ARES("Ares");
 static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service");
 static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback");
 static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot");
@@ -1306,8 +1305,6 @@ bool LLAppViewer::mainLoop()
 		
 		// Create IO Pump to use for HTTP Requests.
 		gServicePump = new LLPumpIO(gAPRPoolp);
-		LLHTTPClient::setPump(*gServicePump);
-		LLCurl::setCAFile(gDirUtilp->getCAFile());
 		
 		// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
 		
@@ -1426,26 +1423,6 @@ bool LLAppViewer::mainLoop()
 					LL_RECORD_BLOCK_TIME(FTM_IDLE);
 					idle();
 
-					if (gAres != NULL && gAres->isInitialized())
-					{
-						pingMainloopTimeout("Main:ServicePump");				
-						LL_RECORD_BLOCK_TIME(FTM_PUMP);
-						{
-							LL_RECORD_BLOCK_TIME(FTM_PUMP_ARES);
-							gAres->process();
-						}
-						{
-							LL_RECORD_BLOCK_TIME(FTM_PUMP_SERVICE);
-							// this pump is necessary to make the login screen show up
-							gServicePump->pump();
-
-							{
-								LL_RECORD_BLOCK_TIME(FTM_SERVICE_CALLBACK);
-								gServicePump->callback();
-							}
-						}
-					}
-					
 					resumeMainloopTimeout();
 				}
  
@@ -1550,11 +1527,6 @@ bool LLAppViewer::mainLoop()
 				}
 				gMeshRepo.update() ;
 				
-				if(!LLCurl::getCurlThread()->update(1))
-				{
-					LLCurl::getCurlThread()->pause() ; //nothing in the curl thread.
-				}
-
 				if(!total_work_pending) //pause texture fetching threads if nothing to process.
 				{
 					LLAppViewer::getTextureCache()->pause();
@@ -1992,7 +1964,6 @@ bool LLAppViewer::cleanup()
 		pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
 		pending += LLVFSThread::updateClass(0);
 		pending += LLLFSThread::updateClass(0);
-		pending += LLCurl::getCurlThread()->update(1) ;
 		F64 idle_time = idleTimer.getElapsedTimeF64();
 		if(!pending)
 		{
@@ -2004,7 +1975,6 @@ bool LLAppViewer::cleanup()
 			break;
 		}
 	}
-	LLCurl::getCurlThread()->pause() ;
 
 	// Delete workers first
 	// shotdown all worker threads before deleting them in case of co-dependencies
@@ -2019,17 +1989,9 @@ bool LLAppViewer::cleanup()
 	LL_INFOS() << "Shutting down message system" << LL_ENDL;
 	end_messaging_system();
 
-	// *NOTE:Mani - The following call is not thread safe. 
-	LL_CHECK_MEMORY
-	LLCurl::cleanupClass();
-	LL_CHECK_MEMORY
-
 	// Non-LLCurl libcurl library
 	mAppCoreHttp.cleanup();
 
-	// NOTE The following call is not thread safe. 
-	ll_cleanup_ares();
-
 	LLFilePickerThread::cleanupClass();
 
 	//MUST happen AFTER LLCurl::cleanupClass
@@ -2115,6 +2077,7 @@ bool LLAppViewer::cleanup()
 	}
 	LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
 	LLProxy::cleanupClass();
+    LLCore::LLHttp::cleanup();
 
 	LLWearableType::cleanupClass();
 
@@ -3354,7 +3317,7 @@ LLSD LLAppViewer::getViewerInfo() const
 #endif
 
 	info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
-	info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+	info["LIBCURL_VERSION"] = LLCore::LLHttp::getCURLVersion();
 	info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
 	bool want_fullname = true;
 	info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
@@ -4700,31 +4663,6 @@ void LLAppViewer::saveNameCache()
 }
 
 
-void LLAppViewer::saveExperienceCache()
-{
-	std::string filename =
-		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
-	LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL;
-	llofstream cache_stream(filename.c_str());
-	if(cache_stream.is_open())
-	{
-		LLExperienceCache::exportFile(cache_stream);
-	}
-}
-
-void LLAppViewer::loadExperienceCache()
-{
-	std::string filename =
-		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml");
-	LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL;
-	llifstream cache_stream(filename.c_str());
-	if(cache_stream.is_open())
-	{
-		LLExperienceCache::importFile(cache_stream);
-	}
-}
-
-
 /*!	@brief		This class is an LLFrameTimer that can be created with
 				an elapsed time that starts counting up from the given value
 				rather than 0.0.
@@ -4920,7 +4858,6 @@ void LLAppViewer::idle()
 	    // floating throughout the various object lists.
 	    //
 		idleNameCache();
-		idleExperienceCache();
 		idleNetwork();
 	    	        
 
@@ -5350,22 +5287,6 @@ void LLAppViewer::idleNameCache()
 	LLAvatarNameCache::idle();
 }
 
-void LLAppViewer::idleExperienceCache()
-{
-	LLViewerRegion* region = gAgent.getRegion();
-	if (!region) return;
-	
-	std::string lookup_url=region->getCapability("GetExperienceInfo"); 
-	if(!lookup_url.empty() && *lookup_url.rbegin() != '/')
-	{
-		lookup_url += '/';
-	}
-	
-	LLExperienceCache::setLookupURL(lookup_url);
-
-	LLExperienceCache::idle();
-}
-
 //
 // Handle messages, and all message related stuff
 //
@@ -5528,7 +5449,9 @@ void LLAppViewer::disconnectViewer()
 	}
 
 	saveNameCache();
-	saveExperienceCache();
+    LLExperienceCache *expCache = LLExperienceCache::getIfExists();
+    if (expCache)
+        expCache->cleanup();
 
 	// close inventory interface, close all windows
 	LLFloaterInventory::cleanup();
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 718871138eba3350cb37456bd653f51d504b4baf..e8a1ca036b8887bbf294b392b553248a8ff6c624 100755
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -122,9 +122,6 @@ class LLAppViewer : public LLApp
     void loadNameCache();
     void saveNameCache();
 
-	void loadExperienceCache();
-	void saveExperienceCache();
-
 	void removeMarkerFiles();
 	
 	void removeDumpDir();
@@ -233,7 +230,6 @@ class LLAppViewer : public LLApp
     void idle(); 
     void idleShutdown();
 	// update avatar SLID and display name caches
-	void idleExperienceCache();
 	void idleNameCache();
     void idleNetwork();
 
diff --git a/indra/newview/llassetuploadqueue.cpp b/indra/newview/llassetuploadqueue.cpp
deleted file mode 100755
index 359ee1e221b40dfcc244d4edf3c9ac562f20008b..0000000000000000000000000000000000000000
--- a/indra/newview/llassetuploadqueue.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/** 
- * @file llassetupload.cpp
- * @brief Serializes asset upload request
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llassetuploadqueue.h"
-#include "llviewerregion.h"
-#include "llviewerobjectlist.h"
-
-#include "llassetuploadresponders.h"
-#include "llsd.h"
-#include <iostream>
-
-class LLAssetUploadChainResponder : public LLUpdateTaskInventoryResponder
-{
-	LOG_CLASS(LLAssetUploadChainResponder);
-public:
-	
-	LLAssetUploadChainResponder(const LLSD& post_data,
-								const std::string& file_name,
-								const LLUUID& queue_id,
-								U8* data, 
-								U32 data_size,
-								std::string script_name,
-								LLAssetUploadQueueSupplier *supplier) :
-		LLUpdateTaskInventoryResponder(post_data, file_name, queue_id, LLAssetType::AT_LSL_TEXT),
-		mSupplier(supplier),
-		mData(data),
-		mDataSize(data_size),
-		mScriptName(script_name)
-	{
-	}
-
-	virtual ~LLAssetUploadChainResponder() 
-	{
-		if(mSupplier)
-		{
-			LLAssetUploadQueue *queue = mSupplier->get();
-			if (queue)
-			{
-				// Give ownership of supplier back to queue.
-				queue->mSupplier = mSupplier;
-				mSupplier = NULL;
-			}
-		}
-		delete mSupplier;
-		delete mData;
-	}
-	
-protected:
-	virtual void httpFailure()
-	{
-		// Parent class will spam the failure.
-		//LL_WARNS() << dumpResponse() << LL_ENDL;
-		LLUpdateTaskInventoryResponder::httpFailure();
-		LLAssetUploadQueue *queue = mSupplier->get();
-		if (queue)
-		{
-			queue->request(&mSupplier);
-		}
-	}
-
-	virtual void httpSuccess()
-	{
-		LLUpdateTaskInventoryResponder::httpSuccess();
-		LLAssetUploadQueue *queue = mSupplier->get();
-		if (queue)
-		{
-			// Responder is reused across 2 phase upload,
-			// so only start next upload after 2nd phase complete.
-			const std::string& state = getContent()["state"].asStringRef();
-			if(state == "complete")
-			{
-				queue->request(&mSupplier);
-			}
-		}
-	}
-	
-public:
-	virtual void uploadUpload(const LLSD& content)
-	{
-		std::string uploader = content["uploader"];
-
-		mSupplier->log(std::string("Compiling " + mScriptName).c_str());
-		LL_INFOS() << "Compiling " << LL_ENDL;
-
-		// postRaw takes ownership of mData and will delete it.
-		LLHTTPClient::postRaw(uploader, mData, mDataSize, this);
-		mData = NULL;
-		mDataSize = 0;
-	}
-
-	virtual void uploadComplete(const LLSD& content)
-	{
-		// Bytecode save completed
-		if (content["compiled"])
-		{
-			mSupplier->log("Compilation succeeded");
-			LL_INFOS() << "Compiled!" << LL_ENDL;
-		}
-		else
-		{
-			LLSD compile_errors = content["errors"];
-			for(LLSD::array_const_iterator line	= compile_errors.beginArray();
-				line < compile_errors.endArray(); line++)
-			{
-				std::string str = line->asString();
-				str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
-				mSupplier->log(str);
-				LL_INFOS() << content["errors"] << LL_ENDL;
-			}
-		}
-		LLUpdateTaskInventoryResponder::uploadComplete(content);
-	}
-
-	LLAssetUploadQueueSupplier *mSupplier;
-	U8* mData;
-	U32 mDataSize;
-	std::string mScriptName;
-};
-
-
-LLAssetUploadQueue::LLAssetUploadQueue(LLAssetUploadQueueSupplier *supplier) :
-	mSupplier(supplier)
-{
-}
-
-//virtual 
-LLAssetUploadQueue::~LLAssetUploadQueue()
-{
-	delete mSupplier;
-}
-
-// Takes ownership of supplier.
-void LLAssetUploadQueue::request(LLAssetUploadQueueSupplier** supplier)
-{
-	if (mQueue.empty())
-		return;
-
-	UploadData data = mQueue.front();
-	mQueue.pop_front();
-	
-	LLSD body;
-	body["task_id"] = data.mTaskId;
-	body["item_id"] = data.mItemId;
-	body["is_script_running"] = data.mIsRunning;
-	body["target"] = data.mIsTargetMono? "mono" : "lsl2";
-	body["experience"] = data.mExperienceId;
-
-	std::string url = "";
-	LLViewerObject* object = gObjectList.findObject(data.mTaskId);
-	if (object)
-	{
-		url = object->getRegion()->getCapability("UpdateScriptTask");
-		LLHTTPClient::post(url, body,
-							new LLAssetUploadChainResponder(
-								body, data.mFilename, data.mQueueId, 
-								data.mData, data.mDataSize, data.mScriptName, *supplier));
-	}
-
-	*supplier = NULL;
-}
-
-void LLAssetUploadQueue::queue(const std::string& filename,
-							   const LLUUID& task_id,
-							   const LLUUID& item_id,
-							   BOOL is_running, 
-							   BOOL is_target_mono, 
-							   const LLUUID& queue_id,
-							   U8* script_data,
-							   U32 data_size,
-							   std::string script_name,
-							   const LLUUID& experience_id)
-{
-	UploadData data;
-	data.mTaskId = task_id;
-	data.mItemId = item_id;
-	data.mIsRunning = is_running;
-	data.mIsTargetMono = is_target_mono;
-	data.mQueueId = queue_id;
-	data.mFilename = filename;
-	data.mData = script_data;
-	data.mDataSize = data_size;
-	data.mScriptName = script_name;
-	data.mExperienceId = experience_id;
-			
-	mQueue.push_back(data);
-
-	if(mSupplier)
-	{
-		request(&mSupplier);
-	}	
-}
-
-LLAssetUploadQueueSupplier::~LLAssetUploadQueueSupplier()
-{
-}
diff --git a/indra/newview/llassetuploadqueue.h b/indra/newview/llassetuploadqueue.h
deleted file mode 100755
index 2ceee8f7008f9f15998fafac044f752bf3227485..0000000000000000000000000000000000000000
--- a/indra/newview/llassetuploadqueue.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/** 
- * @file llassetuploadqueue.h
- * @brief Serializes asset upload request
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSETUPLOADQUEUE_H
-#define LL_LLASSETUPLOADQUEUE_H
-
-#include "lluuid.h"
-
-#include <string>
-#include <deque>
-
-class LLAssetUploadQueueSupplier;
-
-class LLAssetUploadQueue
-{
-public:
-
-	// Takes ownership of supplier.
-	LLAssetUploadQueue(LLAssetUploadQueueSupplier* supplier);
-	virtual ~LLAssetUploadQueue();
-
-	void queue(const std::string& filename,
-			   const LLUUID& task_id,
-			   const LLUUID& item_id,
-			   BOOL is_running, 
-			   BOOL is_target_mono, 
-			   const LLUUID& queue_id,
-			   U8* data,
-			   U32 data_size,
-			   std::string script_name, 
-			   const LLUUID& experience_id);
-
-	bool isEmpty() const {return mQueue.empty();}
-
-private:
-
-	friend class LLAssetUploadChainResponder;
-
-	struct UploadData
-	{
-		std::string mFilename;
-		LLUUID mTaskId;
-		LLUUID mItemId;
-		BOOL mIsRunning;
-		BOOL mIsTargetMono;
-		LLUUID mQueueId;
-		U8* mData;
-		U32 mDataSize;
-		std::string mScriptName;
-		LLUUID mExperienceId;
-	};
-
-	// Ownership of mSupplier passed to currently waiting responder
-	// and returned to queue when no requests in progress.
-	LLAssetUploadQueueSupplier* mSupplier;
-	std::deque<UploadData> mQueue;
-
-	// Passes on ownership of mSupplier if request is made.
-	void request(LLAssetUploadQueueSupplier** supplier);
-};
-
-class LLAssetUploadQueueSupplier
-{
-public:
-	virtual ~LLAssetUploadQueueSupplier();
-	virtual LLAssetUploadQueue* get() const = 0;
-	virtual void log(std::string message) const = 0;
-};
-
-#endif // LL_LLASSETUPLOADQUEUE_H
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
deleted file mode 100755
index d2b1dcbf359d3365263d8720934067be261d95c4..0000000000000000000000000000000000000000
--- a/indra/newview/llassetuploadresponders.cpp
+++ /dev/null
@@ -1,1148 +0,0 @@
-/**
- * @file llassetuploadresponders.cpp
- * @brief Processes responses received for asset upload requests.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */ 
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llassetuploadresponders.h"
-
-// viewer includes
-#include "llagent.h"
-#include "llcompilequeue.h"
-#include "llbuycurrencyhtml.h"
-#include "llfilepicker.h"
-#include "llinventorydefines.h"
-#include "llinventoryobserver.h"
-#include "llinventorypanel.h"
-#include "llpermissionsflags.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewscript.h"
-#include "llpreviewgesture.h"
-#include "llgesturemgr.h"
-#include "llstatusbar.h"		// sendMoneyBalanceRequest()
-#include "llsdserialize.h"
-#include "lluploaddialog.h"
-#include "llviewerobject.h"
-#include "llviewercontrol.h"
-#include "llviewerobjectlist.h"
-#include "llviewermenufile.h"
-#include "llviewertexlayer.h"
-#include "llviewerwindow.h"
-#include "lltrans.h"
-
-// library includes
-#include "lldir.h"
-#include "lleconomy.h"
-#include "llfloaterreg.h"
-#include "llfocusmgr.h"
-#include "llnotificationsutil.h"
-#include "llscrolllistctrl.h"
-#include "llsdserialize.h"
-#include "llsdutil.h"
-#include "llvfs.h"
-
-void dialog_refresh_all();
-
-void on_new_single_inventory_upload_complete(
-	LLAssetType::EType asset_type,
-	LLInventoryType::EType inventory_type,
-	const std::string inventory_type_string,
-	const LLUUID& item_folder_id,
-	const std::string& item_name,
-	const std::string& item_description,
-	const LLSD& server_response,
-	S32 upload_price)
-{
-	bool success = false;
-
-	if ( upload_price > 0 )
-	{
-		// this upload costed us L$, update our balance
-		// and display something saying that it cost L$
-		LLStatusBar::sendMoneyBalanceRequest();
-
-		LLSD args;
-		args["AMOUNT"] = llformat("%d", upload_price);
-		LLNotificationsUtil::add("UploadPayment", args);
-	}
-
-	if( item_folder_id.notNull() )
-	{
-		U32 everyone_perms = PERM_NONE;
-		U32 group_perms = PERM_NONE;
-		U32 next_owner_perms = PERM_ALL;
-		if( server_response.has("new_next_owner_mask") )
-		{
-			// The server provided creation perms so use them.
-			// Do not assume we got the perms we asked for in
-			// since the server may not have granted them all.
-			everyone_perms = server_response["new_everyone_mask"].asInteger();
-			group_perms = server_response["new_group_mask"].asInteger();
-			next_owner_perms = server_response["new_next_owner_mask"].asInteger();
-		}
-		else 
-		{
-			// The server doesn't provide creation perms
-			// so use old assumption-based perms.
-			if( inventory_type_string != "snapshot")
-			{
-				next_owner_perms = PERM_MOVE | PERM_TRANSFER;
-			}
-		}
-
-		LLPermissions new_perms;
-		new_perms.init(
-			gAgent.getID(),
-			gAgent.getID(),
-			LLUUID::null,
-			LLUUID::null);
-
-		new_perms.initMasks(
-			PERM_ALL,
-			PERM_ALL,
-			everyone_perms,
-			group_perms,
-			next_owner_perms);
-
-		U32 inventory_item_flags = 0;
-		if (server_response.has("inventory_flags"))
-		{
-			inventory_item_flags = (U32) server_response["inventory_flags"].asInteger();
-			if (inventory_item_flags != 0)
-			{
-				LL_INFOS() << "inventory_item_flags " << inventory_item_flags << LL_ENDL;
-			}
-		}
-		S32 creation_date_now = time_corrected();
-		LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
-			server_response["new_inventory_item"].asUUID(),
-			item_folder_id,
-			new_perms,
-			server_response["new_asset"].asUUID(),
-			asset_type,
-			inventory_type,
-			item_name,
-			item_description,
-			LLSaleInfo::DEFAULT,
-			inventory_item_flags,
-			creation_date_now);
-
-		gInventory.updateItem(item);
-		gInventory.notifyObservers();
-		success = true;
-
-		// Show the preview panel for textures and sounds to let
-		// user know that the image (or snapshot) arrived intact.
-		LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel();
-		if ( panel )
-		{
-			LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
-
-			panel->setSelection(
-				server_response["new_inventory_item"].asUUID(),
-				TAKE_FOCUS_NO);
-
-			// restore keyboard focus
-			gFocusMgr.setKeyboardFocus(focus);
-		}
-	}
-	else
-	{
-		LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
-	}
-
-	// remove the "Uploading..." message
-	LLUploadDialog::modalUploadFinished();	
-
-	// Let the Snapshot floater know we have finished uploading a snapshot to inventory.
-	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
-	if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot)
-	{
-		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
-	}
-}
-
-LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
-											   const LLUUID& vfile_id,
-											   LLAssetType::EType asset_type)
-	: LLHTTPClient::Responder(),
-	  mPostData(post_data),
-	  mVFileID(vfile_id),
-	  mAssetType(asset_type)
-{
-	if (!gVFS->getExists(vfile_id, asset_type))
-	{
-		LL_WARNS() << "LLAssetUploadResponder called with nonexistant vfile_id" << LL_ENDL;
-		mVFileID.setNull();
-		mAssetType = LLAssetType::AT_NONE;
-		return;
-	}
-}
-
-LLAssetUploadResponder::LLAssetUploadResponder(
-	const LLSD &post_data,
-	const std::string& file_name, 
-	LLAssetType::EType asset_type)
-	: LLHTTPClient::Responder(),
-	  mPostData(post_data),
-	  mFileName(file_name),
-	  mAssetType(asset_type)
-{
-}
-
-LLAssetUploadResponder::~LLAssetUploadResponder()
-{
-	if (!mFileName.empty())
-	{
-		// Delete temp file
-		LLFile::remove(mFileName);
-	}
-}
-
-// virtual
-void LLAssetUploadResponder::httpFailure()
-{
-	// *TODO: Add adaptive retry policy?
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	std::string reason;
-	if (isHttpClientErrorStatus(getStatus()))
-	{
-		reason = "Error in upload request.  Please visit "
-			"http://secondlife.com/support for help fixing this problem.";
-	}
-	else
-	{
-		reason = "The server is experiencing unexpected "
-			"difficulties.";
-	}
-	LLSD args;
-	args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-	args["REASON"] = reason;
-	LLNotificationsUtil::add("CannotUploadReason", args);
-
-	// unfreeze script preview
-	if(mAssetType == LLAssetType::AT_LSL_TEXT)
-	{
-		LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", mPostData["item_id"]);
-		if (preview)
-		{
-			LLSD errors;
-			errors.append(LLTrans::getString("UploadFailed") + reason);
-			preview->callbackLSLCompileFailed(errors);
-		}
-	}
-
-	LLUploadDialog::modalUploadFinished();
-	LLFilePicker::instance().reset();  // unlock file picker when bulk upload fails
-}
-
-//virtual 
-void LLAssetUploadResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	LL_DEBUGS() << "LLAssetUploadResponder::result from capabilities" << LL_ENDL;
-
-	const std::string& state = content["state"].asStringRef();
-
-	if (state == "upload")
-	{
-		uploadUpload(content);
-	}
-	else if (state == "complete")
-	{
-		// rename file in VFS with new asset id
-		if (mFileName.empty())
-		{
-			// rename the file in the VFS to the actual asset id
-			// LL_INFOS() << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << LL_ENDL;
-			gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType);
-		}
-		uploadComplete(content);
-	}
-	else
-	{
-		uploadFailure(content);
-	}
-}
-
-void LLAssetUploadResponder::uploadUpload(const LLSD& content)
-{
-	const std::string& uploader = content["uploader"].asStringRef();
-	if (mFileName.empty())
-	{
-		LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this);
-	}
-	else
-	{
-		LLHTTPClient::postFile(uploader, mFileName, this);
-	}
-}
-
-void LLAssetUploadResponder::uploadFailure(const LLSD& content)
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-
-	// unfreeze script preview
-	if(mAssetType == LLAssetType::AT_LSL_TEXT)
-	{
-		LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", mPostData["item_id"]);
-		if (preview)
-		{
-			LLSD errors;
-			errors.append(LLTrans::getString("UploadFailed") + content["message"].asString());
-			preview->callbackLSLCompileFailed(errors);
-		}
-	}
-
-	// remove the "Uploading..." message
-	LLUploadDialog::modalUploadFinished();
-
-	LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
-	if (floater_snapshot)
-	{
-		floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory")));
-	}
-	
-	const std::string& reason = content["state"].asStringRef();
-	// deal with L$ errors
-	if (reason == "insufficient funds")
-	{
-		S32 price = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-		LLStringUtil::format_map_t args;
-		args["AMOUNT"] = llformat("%d", price);
-		LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("uploading_costs", args), price );
-	}
-	else
-	{
-		LLSD args;
-		args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
-		args["REASON"] = content["message"].asString();
-		LLNotificationsUtil::add("CannotUploadReason", args);
-	}
-}
-
-void LLAssetUploadResponder::uploadComplete(const LLSD& content)
-{
-}
-
-LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
-	const LLSD& post_data,
-	const LLUUID& vfile_id,
-	LLAssetType::EType asset_type)
-	: LLAssetUploadResponder(post_data, vfile_id, asset_type)
-{
-}
-
-LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
-	const LLSD& post_data,
-	const std::string& file_name,
-	LLAssetType::EType asset_type)
-	: LLAssetUploadResponder(post_data, file_name, asset_type)
-{
-}
-
-// virtual
-void LLNewAgentInventoryResponder::httpFailure()
-{
-	LLAssetUploadResponder::httpFailure();
-	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE);
-}
-
-
-//virtual 
-void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content)
-{
-	LLAssetUploadResponder::uploadFailure(content);
-
-	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], FALSE);
-}
-
-//virtual 
-void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
-{
-	LL_DEBUGS() << "LLNewAgentInventoryResponder::result from capabilities" << LL_ENDL;
-	
-	//std::ostringstream llsdxml;
-	//LLSDSerialize::toXML(content, llsdxml);
-	//LL_INFOS() << "upload complete content:\n " << llsdxml.str() << LL_ENDL;
-
-	LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
-	LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());
-	S32 expected_upload_cost = 0;
-
-	// Update L$ and ownership credit information
-	// since it probably changed on the server
-	if (asset_type == LLAssetType::AT_TEXTURE ||
-		asset_type == LLAssetType::AT_SOUND ||
-		asset_type == LLAssetType::AT_ANIMATION ||
-		asset_type == LLAssetType::AT_MESH)
-	{
-		expected_upload_cost = 
-			LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-	}
-
-	on_new_single_inventory_upload_complete(
-		asset_type,
-		inventory_type,
-		mPostData["asset_type"].asString(),
-		mPostData["folder_id"].asUUID(),
-		mPostData["name"],
-		mPostData["description"],
-		content,
-		expected_upload_cost);
-
-	// continue uploading for bulk uploads
-
-	// *FIX: This is a pretty big hack. What this does is check the
-	// file picker if there are any more pending uploads. If so,
-	// upload that file.
-	std::string next_file = LLFilePicker::instance().getNextFile();
-	if(!next_file.empty())
-	{
-		std::string name = gDirUtilp->getBaseFileName(next_file, true);
-
-		std::string asset_name = name;
-		LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
-		LLStringUtil::replaceChar(asset_name, '|', '?');
-		LLStringUtil::stripNonprintable(asset_name);
-		LLStringUtil::trim(asset_name);
-
-		// Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
-		// and use them for each next file to be uploaded. Note the requested perms are not the same as the
-		U32 everyone_perms =
-			content.has("new_everyone_mask") ?
-			content["new_everyone_mask"].asInteger() :
-			PERM_NONE;
-
-		U32 group_perms =
-			content.has("new_group_mask") ?
-			content["new_group_mask"].asInteger() :
-			PERM_NONE;
-
-		U32 next_owner_perms =
-			content.has("new_next_owner_mask") ?
-			content["new_next_owner_mask"].asInteger() :
-			PERM_NONE;
-
-		std::string display_name = LLStringUtil::null;
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
-		void *userdata = NULL;
-
-		upload_new_resource(
-			next_file,
-			asset_name,
-			asset_name,
-			0,
-			LLFolderType::FT_NONE,
-			LLInventoryType::IT_NONE,
-			next_owner_perms,
-			group_perms,
-			everyone_perms,
-			display_name,
-			callback,
-			LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(),
-			userdata);
-	}
-
-	//LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);
-}
-
-LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
-	const LLSD& post_data,
-	const LLUUID& vfile_id,
-	LLAssetType::EType asset_type)
-	: LLAssetUploadResponder(post_data, vfile_id, asset_type)
-{
-}
-
-LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
-	const LLSD& post_data,
-	const std::string& file_name,
-	LLAssetType::EType asset_type)
-	: LLAssetUploadResponder(post_data, file_name, asset_type)
-{
-}
-
-//virtual 
-void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
-{
-	LL_INFOS() << "LLUpdateAgentInventoryResponder::result from capabilities" << LL_ENDL;
-	LLUUID item_id = mPostData["item_id"];
-
-	LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id);
-	if(!item)
-	{
-		LL_WARNS() << "Inventory item for " << mVFileID
-			<< " is no longer in agent inventory." << LL_ENDL;
-		return;
-	}
-
-	// Update viewer inventory item
-	LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
-	new_item->setAssetUUID(content["new_asset"].asUUID());
-	gInventory.updateItem(new_item);
-	gInventory.notifyObservers();
-
-	LL_INFOS() << "Inventory item " << item->getName() << " saved into "
-		<< content["new_asset"].asString() << LL_ENDL;
-
-	LLInventoryType::EType inventory_type = new_item->getInventoryType();
-	switch(inventory_type)
-	{
-	  case LLInventoryType::IT_NOTECARD:
-	  {
-		  // Update the UI with the new asset.
-		  LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
-		  if(nc)
-		  {
-			  // *HACK: we have to delete the asset in the VFS so
-			  // that the viewer will redownload it. This is only
-			  // really necessary if the asset had to be modified by
-			  // the uploader, so this can be optimized away in some
-			  // cases. A better design is to have a new uuid if the
-			  // script actually changed the asset.
-			  if(nc->hasEmbeddedInventory())
-			  {
-				  gVFS->removeFile(content["new_asset"].asUUID(), LLAssetType::AT_NOTECARD);
-			  }
-			  nc->refreshFromInventory(new_item->getUUID());
-		  }
-		  break;
-	  }
-	  case LLInventoryType::IT_LSL:
-	  {
-		  // Find our window and close it if requested.
-		  LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", LLSD(item_id));
-		  if (preview)
-		  {
-			  // Bytecode save completed
-			  if (content["compiled"])
-			  {
-				  preview->callbackLSLCompileSucceeded();
-			  }
-			  else
-			  {
-				  preview->callbackLSLCompileFailed(content["errors"]);
-			  }
-		  }
-		  break;
-	  }
-
-	  case LLInventoryType::IT_GESTURE:
-	  {
-		  // If this gesture is active, then we need to update the in-memory
-		  // active map with the new pointer.				
-		  if (LLGestureMgr::instance().isGestureActive(item_id))
-		  {
-			  LLUUID asset_id = new_item->getAssetUUID();
-			  LLGestureMgr::instance().replaceGesture(item_id, asset_id);
-			  gInventory.notifyObservers();
-		  }				
-
-		  //gesture will have a new asset_id
-		  LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(item_id));
-		  if(previewp)
-		  {
-			  previewp->onUpdateSucceeded();	
-		  }			
-				
-		  break;
-	  }
-	  case LLInventoryType::IT_WEARABLE:
-	  default:
-		break;
-	}
-}
-
-
-LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
-																 const LLUUID& vfile_id,
-																 LLAssetType::EType asset_type)
-: LLAssetUploadResponder(post_data, vfile_id, asset_type)
-{
-}
-
-LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
-															   const std::string& file_name, 
-															   LLAssetType::EType asset_type)
-: LLAssetUploadResponder(post_data, file_name, asset_type)
-{
-}
-
-LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
-															   const std::string& file_name,
-															   const LLUUID& queue_id, 
-															   LLAssetType::EType asset_type)
-: LLAssetUploadResponder(post_data, file_name, asset_type), mQueueId(queue_id)
-{
-}
-
-//virtual 
-void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
-{
-	LL_INFOS() << "LLUpdateTaskInventoryResponder::result from capabilities" << LL_ENDL;
-	LLUUID item_id = mPostData["item_id"];
-	LLUUID task_id = mPostData["task_id"];
-
-	dialog_refresh_all();
-	
-	switch(mAssetType)
-	{
-	  case LLAssetType::AT_NOTECARD:
-	  {
-		  // Update the UI with the new asset.
-		  LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(item_id));
-		  if(nc)
-		  {
-			  // *HACK: we have to delete the asset in the VFS so
-			  // that the viewer will redownload it. This is only
-			  // really necessary if the asset had to be modified by
-			  // the uploader, so this can be optimized away in some
-			  // cases. A better design is to have a new uuid if the
-			  // script actually changed the asset.
-			  if(nc->hasEmbeddedInventory())
-			  {
-				  gVFS->removeFile(content["new_asset"].asUUID(),
-								   LLAssetType::AT_NOTECARD);
-			  }
-			  nc->setAssetId(content["new_asset"].asUUID());
-			  nc->refreshFromInventory();
-		  }
-		  break;
-	  }
-	  case LLAssetType::AT_LSL_TEXT:
-	  {
-		  if(mQueueId.notNull())
-		  {
-			  LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mQueueId);
-			  if(NULL != queue)
-			  {
-				  queue->removeItemByItemID(item_id);
-			  }
-		  }
-		  else
-		  {
-			  LLSD floater_key;
-			  floater_key["taskid"] = task_id;
-			  floater_key["itemid"] = item_id;
-			  LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key);
-			  if (preview)
-			  {
-				  // Bytecode save completed
-				  if (content["compiled"])
-				  {
-					  preview->callbackLSLCompileSucceeded(task_id, item_id, mPostData["is_script_running"]);
-				  }
-				  else
-				  {
-					  preview->callbackLSLCompileFailed(content["errors"]);
-				  }
-			  }
-		  }
-		  break;
-	  }
-	  default:
-		break;
-	}
-}
-
-
-/////////////////////////////////////////////////////
-// LLNewAgentInventoryVariablePriceResponder::Impl //
-/////////////////////////////////////////////////////
-class LLNewAgentInventoryVariablePriceResponder::Impl
-{
-public:
-	Impl(
-		const LLUUID& vfile_id,
-		LLAssetType::EType asset_type,
-		const LLSD& inventory_data) :
-		mVFileID(vfile_id),
-		mAssetType(asset_type),
-		mInventoryData(inventory_data),
-		mFileName("")
-	{
-		if (!gVFS->getExists(vfile_id, asset_type))
-		{
-			LL_WARNS()
-				<< "LLAssetUploadResponder called with nonexistant "
-				<< "vfile_id " << vfile_id << LL_ENDL;
-			mVFileID.setNull();
-			mAssetType = LLAssetType::AT_NONE;
-		}
-	}
-
-	Impl(
-		const std::string& file_name,
-		LLAssetType::EType asset_type,
-		const LLSD& inventory_data) :
-		mFileName(file_name),
-		mAssetType(asset_type),
-		mInventoryData(inventory_data)
-	{
-		mVFileID.setNull();
-	}
-
-	std::string getFilenameOrIDString() const
-	{
-		return (mFileName.empty() ? mVFileID.asString() : mFileName);
-	}
-
-	LLUUID getVFileID() const
-	{
-		return mVFileID;
-	}
-
-	std::string getFilename() const
-	{
-		return mFileName;
-	}
-
-	LLAssetType::EType getAssetType() const
-	{
-		return mAssetType;
-	}
-
-	LLInventoryType::EType getInventoryType() const
-	{
-		return LLInventoryType::lookup(
-			mInventoryData["inventory_type"].asString());
-	}
-
-	std::string getInventoryTypeString() const
-	{
-		return mInventoryData["inventory_type"].asString();
-	}
-
-	LLUUID getFolderID() const
-	{
-		return mInventoryData["folder_id"].asUUID();
-	}
-
-	std::string getItemName() const
-	{
-		return mInventoryData["name"].asString();
-	}
-
-	std::string getItemDescription() const
-	{
-		return mInventoryData["description"].asString();
-	}
-
-	void displayCannotUploadReason(const std::string& reason)
-	{
-		LLSD args;
-		args["FILE"] = getFilenameOrIDString();
-		args["REASON"] = reason;
-
-
-		LLNotificationsUtil::add("CannotUploadReason", args);
-		LLUploadDialog::modalUploadFinished();
-	}
-
-	void onApplicationLevelError(const LLSD& error)
-	{
-		static const std::string _IDENTIFIER = "identifier";
-
-		static const std::string _INSUFFICIENT_FUNDS =
-			"NewAgentInventory_InsufficientLindenDollarBalance";
-		static const std::string _MISSING_REQUIRED_PARAMETER =
-			"NewAgentInventory_MissingRequiredParamater";
-		static const std::string _INVALID_REQUEST_BODY =
-			"NewAgentInventory_InvalidRequestBody";
-		static const std::string _RESOURCE_COST_DIFFERS =
-			"NewAgentInventory_ResourceCostDiffers";
-
-		static const std::string _MISSING_PARAMETER = "missing_parameter";
-		static const std::string _INVALID_PARAMETER = "invalid_parameter";
-		static const std::string _MISSING_RESOURCE = "missing_resource";
-		static const std::string _INVALID_RESOURCE = "invalid_resource";
-
-		// TODO* Add the other error_identifiers
-
-		std::string error_identifier = error[_IDENTIFIER].asString();
-
-		// TODO*: Pull these user visible strings from an xml file
-		// to be localized
-		if ( _INSUFFICIENT_FUNDS == error_identifier )
-		{
-			displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload.");
-		}
-		else if ( _MISSING_REQUIRED_PARAMETER == error_identifier )
-		{
-			// Missing parameters
-			if (error.has(_MISSING_PARAMETER) )
-			{
-				std::string message = 
-					"Upload request was missing required parameter '[P]'";
-				LLStringUtil::replaceString(
-					message,
-					"[P]",
-					error[_MISSING_PARAMETER].asString());
-
-				displayCannotUploadReason(message);
-			}
-			else
-			{
-				std::string message = 
-					"Upload request was missing a required parameter";
-				displayCannotUploadReason(message);					
-			}
-		}
-		else if ( _INVALID_REQUEST_BODY == error_identifier )
-		{
-			// Invalid request body, check to see if 
-			// a particular parameter was invalid
-			if ( error.has(_INVALID_PARAMETER) )
-			{
-				std::string message = "Upload parameter '[P]' is invalid.";
-				LLStringUtil::replaceString(
-					message,
-					"[P]",
-					error[_INVALID_PARAMETER].asString());
-
-				// See if the server also responds with what resource
-				// is missing.
-				if ( error.has(_MISSING_RESOURCE) )
-				{
-					message += "\nMissing resource '[R]'.";
-
-					LLStringUtil::replaceString(
-						message,
-						"[R]",
-						error[_MISSING_RESOURCE].asString());
-				}
-				else if ( error.has(_INVALID_RESOURCE) )
-				{
-					message += "\nInvalid resource '[R]'.";
-
-					LLStringUtil::replaceString(
-						message,
-						"[R]",
-						error[_INVALID_RESOURCE].asString());
-				}
-
-				displayCannotUploadReason(message);
-			}
-			else
-			{
-				std::string message = "Upload request was malformed";
-				displayCannotUploadReason(message);					
-			}
-		}
-		else if ( _RESOURCE_COST_DIFFERS == error_identifier )
-		{
-			displayCannotUploadReason("The resource cost associated with this upload is not consistent with the server.");
-		}
-		else
-		{
-			displayCannotUploadReason("Unknown Error");
-		}
-	}
-
-	void onTransportError()
-	{
-		displayCannotUploadReason(
-				"The server is experiencing unexpected difficulties.");
-	}
-
-	void onTransportError(const LLSD& error)
-	{
-		static const std::string _IDENTIFIER = "identifier";
-
-		static const std::string _SERVER_ERROR_AFTER_CHARGE =
-			"NewAgentInventory_ServerErrorAfterCharge";
-
-		std::string error_identifier = error[_IDENTIFIER].asString();
-
-		// TODO*: Pull the user visible strings from an xml file
-		// to be localized
-
-		if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier )
-		{
-			displayCannotUploadReason(
-				"The server is experiencing unexpected difficulties.  You may have been charged for the upload.");
-		}
-		else
-		{
-			displayCannotUploadReason(
-				"The server is experiencing unexpected difficulties.");
-		}
-	}
-
-	bool uploadConfirmationCallback(
-		const LLSD& notification,
-		const LLSD& response,
-		LLPointer<LLNewAgentInventoryVariablePriceResponder> responder)
-	{
-		S32 option;
-		std::string confirmation_url;
-
-		option = LLNotificationsUtil::getSelectedOption(
-			notification,
-			response);
-
-		confirmation_url =
-			notification["payload"]["confirmation_url"].asString();
-
-		// Yay!  We are confirming or cancelling our upload
-		switch(option)
-		{
-		case 0:
-		    {
-				confirmUpload(confirmation_url, responder);
-			}
-			break;
-		case 1:
-		default:
-			break;
-		}
-
-		return false;
-	}
-
-	void confirmUpload(
-		const std::string& confirmation_url,
-		LLPointer<LLNewAgentInventoryVariablePriceResponder> responder)
-	{
-		if ( getFilename().empty() )
-		{
-			// we have no filename, use virtual file ID instead
-			LLHTTPClient::postFile(
-				confirmation_url,
-				getVFileID(),
-				getAssetType(),
-				responder);
-		}
-		else
-		{
-			LLHTTPClient::postFile(
-				confirmation_url,
-				getFilename(),
-				responder);
-		}
-	}
-
-
-private:
-	std::string mFileName;
-
-	LLSD mInventoryData;
-	LLAssetType::EType mAssetType;
-	LLUUID mVFileID;
-};
-
-///////////////////////////////////////////////
-// LLNewAgentInventoryVariablePriceResponder //
-///////////////////////////////////////////////
-LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
-	const LLUUID& vfile_id,
-	LLAssetType::EType asset_type,
-	const LLSD& inventory_info)
-{
-	mImpl = new Impl(
-		vfile_id,
-		asset_type,
-		inventory_info);
-}
-
-LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
-	const std::string& file_name,
-	LLAssetType::EType asset_type,
-	const LLSD& inventory_info)
-{
-	mImpl = new Impl(
-		file_name,
-		asset_type,
-		inventory_info);
-}
-
-LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResponder()
-{
-	delete mImpl;
-}
-
-void LLNewAgentInventoryVariablePriceResponder::httpFailure()
-{
-	const LLSD& content = getContent();
-	LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
-
-	static const std::string _ERROR = "error";
-	if ( content.has(_ERROR) )
-	{
-		mImpl->onTransportError(content[_ERROR]);
-	}
-	else
-	{
-		mImpl->onTransportError();
-	}
-}
-
-void LLNewAgentInventoryVariablePriceResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	// Parse out application level errors and the appropriate
-	// responses for them
-	static const std::string _ERROR = "error";
-	static const std::string _STATE = "state";
-
-	static const std::string _COMPLETE = "complete";
-	static const std::string _CONFIRM_UPLOAD = "confirm_upload";
-
-	static const std::string _UPLOAD_PRICE = "upload_price";
-	static const std::string _RESOURCE_COST = "resource_cost";
-	static const std::string _RSVP = "rsvp";
-
-	// Check for application level errors
-	if ( content.has(_ERROR) )
-	{
-		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
-		onApplicationLevelError(content[_ERROR]);
-		return;
-	}
-
-	std::string state = content[_STATE];
-	LLAssetType::EType asset_type = mImpl->getAssetType();
-
-	if ( _COMPLETE == state )
-	{
-		// rename file in VFS with new asset id
-		if (mImpl->getFilename().empty())
-		{
-			// rename the file in the VFS to the actual asset id
-			// LL_INFOS() << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << LL_ENDL;
-			gVFS->renameFile(
-				mImpl->getVFileID(),
-				asset_type,
-				content["new_asset"].asUUID(),
-				asset_type);
-		}
-
- 		on_new_single_inventory_upload_complete(
- 			asset_type,
- 			mImpl->getInventoryType(),
-			mImpl->getInventoryTypeString(),
-			mImpl->getFolderID(),
-			mImpl->getItemName(),
-			mImpl->getItemDescription(),
-			content,
-			content[_UPLOAD_PRICE].asInteger());
-
-		// TODO* Add bulk (serial) uploading or add
-		// a super class of this that does so
-	}
-	else if ( _CONFIRM_UPLOAD == state )
-	{
-		showConfirmationDialog(
-			content[_UPLOAD_PRICE].asInteger(),
-			content[_RESOURCE_COST].asInteger(),
-			content[_RSVP].asString());
-	}
-	else
-	{
-		LL_WARNS("Upload") << dumpResponse() << LL_ENDL;
-		onApplicationLevelError("");
-	}
-}
-
-void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError(
-	const LLSD& error)
-{
-	mImpl->onApplicationLevelError(error);
-}
-
-void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog(
-	S32 upload_price,
-	S32 resource_cost,
-	const std::string& confirmation_url)
-{
-	if ( 0 == upload_price )
-	{
-		// don't show confirmation dialog for free uploads, I mean,
-		// they're free!
-
-		// The creating of a new instrusive_ptr(this)
-		// creates a new boost::intrusive_ptr
-		// which is a copy of this.  This code is required because
-		// 'this' is always of type Class* and not the intrusive_ptr,
-		// and thus, a reference to 'this' is not registered
-		// by using just plain 'this'.
-
-		// Since LLNewAgentInventoryVariablePriceResponder is a
-		// reference counted class, it is possible (since the
-		// reference to a plain 'this' would be missed here) that,
-		// when using plain ol' 'this', that this object
-		// would be deleted before the callback is triggered
-		// and cause sadness.
-		mImpl->confirmUpload(
-			confirmation_url,
-			LLPointer<LLNewAgentInventoryVariablePriceResponder>(this));
-	}
-	else
-	{
-		LLSD substitutions;
-		LLSD payload;
-
-		substitutions["PRICE"] = upload_price;
-
-		payload["confirmation_url"] = confirmation_url;
-
-		// The creating of a new instrusive_ptr(this)
-		// creates a new boost::intrusive_ptr
-		// which is a copy of this.  This code is required because
-		// 'this' is always of type Class* and not the intrusive_ptr,
-		// and thus, a reference to 'this' is not registered
-		// by using just plain 'this'.
-
-		// Since LLNewAgentInventoryVariablePriceResponder is a
-		// reference counted class, it is possible (since the
-		// reference to a plain 'this' would be missed here) that,
-		// when using plain ol' 'this', that this object
-		// would be deleted before the callback is triggered
-		// and cause sadness.
-		LLNotificationsUtil::add(
-			"UploadCostConfirmation",
-			substitutions,
-			payload,
-			boost::bind(
-				&LLNewAgentInventoryVariablePriceResponder::Impl::uploadConfirmationCallback,
-				mImpl,
-				_1,
-				_2,
-				LLPointer<LLNewAgentInventoryVariablePriceResponder>(this)));
-	}
-}
-
-
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
deleted file mode 100755
index 7fbebc7481c1f585dacf23f1c13be02276da9aee..0000000000000000000000000000000000000000
--- a/indra/newview/llassetuploadresponders.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * @file llassetuploadresponders.h
- * @brief Processes responses received for asset upload requests.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSETUPLOADRESPONDER_H
-#define LL_LLASSETUPLOADRESPONDER_H
-
-#include "llhttpclient.h"
-
-// Abstract class for supporting asset upload
-// via capabilities
-class LLAssetUploadResponder : public LLHTTPClient::Responder
-{
-protected:
-	LOG_CLASS(LLAssetUploadResponder);
-public:
-	LLAssetUploadResponder(const LLSD& post_data,
-							const LLUUID& vfile_id,
-							LLAssetType::EType asset_type);
-	LLAssetUploadResponder(const LLSD& post_data, 
-							const std::string& file_name,
-							LLAssetType::EType asset_type);
-	~LLAssetUploadResponder();
-
-protected:
-	virtual void httpFailure();
-	virtual void httpSuccess();
-
-public:
-	virtual void uploadUpload(const LLSD& content);
-	virtual void uploadComplete(const LLSD& content);
-	virtual void uploadFailure(const LLSD& content);
-
-protected:
-	LLSD mPostData;
-	LLAssetType::EType mAssetType;
-	LLUUID mVFileID;
-	std::string mFileName;
-};
-
-// TODO*: Remove this once deprecated
-class LLNewAgentInventoryResponder : public LLAssetUploadResponder
-{
-	LOG_CLASS(LLNewAgentInventoryResponder);
-public:
-	LLNewAgentInventoryResponder(
-		const LLSD& post_data,
-		const LLUUID& vfile_id,
-		LLAssetType::EType asset_type);
-	LLNewAgentInventoryResponder(
-		const LLSD& post_data,
-		const std::string& file_name,
-		LLAssetType::EType asset_type);
-	virtual void uploadComplete(const LLSD& content);
-	virtual void uploadFailure(const LLSD& content);
-protected:
-	virtual void httpFailure();
-};
-
-// A base class which goes through and performs some default
-// actions for variable price uploads.  If more specific actions
-// are needed (such as different confirmation messages, etc.)
-// the functions onApplicationLevelError and showConfirmationDialog.
-class LLNewAgentInventoryVariablePriceResponder :
-	public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLNewAgentInventoryVariablePriceResponder);
-public:
-	LLNewAgentInventoryVariablePriceResponder(
-		const LLUUID& vfile_id,
-		LLAssetType::EType asset_type,
-		const LLSD& inventory_info);
-
-	LLNewAgentInventoryVariablePriceResponder(
-		const std::string& file_name,
-		LLAssetType::EType asset_type,
-		const LLSD& inventory_info);
-	virtual ~LLNewAgentInventoryVariablePriceResponder();
-
-private:
-	/* virtual */ void httpFailure();
-	/* virtual */ void httpSuccess();
-
-public:
-	virtual void onApplicationLevelError(
-		const LLSD& error);
-	virtual void showConfirmationDialog(
-		S32 upload_price,
-		S32 resource_cost,
-		const std::string& confirmation_url);
-
-private:
-	class Impl;
-	Impl* mImpl;
-};
-
-class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder
-{
-public:
-	LLUpdateAgentInventoryResponder(const LLSD& post_data,
-								const LLUUID& vfile_id,
-								LLAssetType::EType asset_type);
-	LLUpdateAgentInventoryResponder(const LLSD& post_data,
-								const std::string& file_name,
-											   LLAssetType::EType asset_type);
-	virtual void uploadComplete(const LLSD& content);
-};
-
-class LLUpdateTaskInventoryResponder : public LLAssetUploadResponder
-{
-public:
-	LLUpdateTaskInventoryResponder(const LLSD& post_data,
-								const LLUUID& vfile_id,
-								LLAssetType::EType asset_type);
-	LLUpdateTaskInventoryResponder(const LLSD& post_data,
-								const std::string& file_name,
-								LLAssetType::EType asset_type);
-	LLUpdateTaskInventoryResponder(const LLSD& post_data,
-								const std::string& file_name,
-								const LLUUID& queue_id,
-								LLAssetType::EType asset_type);
-
-	virtual void uploadComplete(const LLSD& content);
-	
-private:
-	LLUUID mQueueId;
-};
-
-#endif // LL_LLASSETUPLOADRESPONDER_H
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index 38e153137c99c9fe27a64482021d597619e5f2ac..470f516db2db18afdacbd1641461d88d535e5597 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -35,7 +35,6 @@
 // external library headers
 // other Linden headers
 #include "llcharacter.h"
-#include "llhttpclient.h"
 #include "lltimer.h"
 #include "llviewercontrol.h"
 #include "llviewermenu.h"
@@ -43,7 +42,10 @@
 #include "llviewerregion.h"
 #include "llvoavatar.h"
 #include "llworld.h"
-
+#include "llhttpsdhandler.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
+#include "llcorehttputil.h"
 
 static	const std::string KEY_AGENTS = "agents";			// map
 static 	const std::string KEY_WEIGHT = "weight";			// integer
@@ -55,166 +57,178 @@ static	const std::string KEY_ERROR = "error";
 
 // Send data updates about once per minute, only need per-frame resolution
 LLFrameTimer LLAvatarRenderInfoAccountant::sRenderInfoReportTimer;
+//LLCore::HttpRequest::ptr_t LLAvatarRenderInfoAccountant::sHttpRequest;
 
-
-// HTTP responder class for GET request for avatar render weight information
-class LLAvatarRenderInfoGetResponder : public LLHTTPClient::Responder
+//=========================================================================
+void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64 regionHandle)
 {
-public:
-	LLAvatarRenderInfoGetResponder(U64 region_handle) : mRegionHandle(region_handle)
-	{
-	}
-
-	virtual void error(U32 statusNum, const std::string& reason)
-	{
-		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if (regionp)
-		{
-			LL_WARNS() << "HTTP error result for avatar weight GET: " << statusNum 
-				<< ", " << reason
-				<< " returned by region " << regionp->getName()
-				<< LL_ENDL;
-		}
-		else
-		{
-			LL_WARNS() << "Avatar render weight GET error recieved but region not found for " 
-				<< mRegionHandle 
-				<< ", error " << statusNum 
-				<< ", " << reason
-				<< LL_ENDL;
-		}
-
-	}
-
-	virtual void result(const LLSD& content)
-	{
-		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if (regionp)
-		{
-			if (LLAvatarRenderInfoAccountant::logRenderInfo())
-			{
-				LL_INFOS() << "LRI: Result for avatar weights request for region " << regionp->getName() << ":" << LL_ENDL;
-			}
-
-			if (content.isMap())
-			{
-				if (content.has(KEY_AGENTS))
-				{
-					const LLSD & agents = content[KEY_AGENTS];
-					if (agents.isMap())
-					{
-						LLSD::map_const_iterator	report_iter = agents.beginMap();
-						while (report_iter != agents.endMap())
-						{
-							LLUUID target_agent_id = LLUUID(report_iter->first);
-							const LLSD & agent_info_map = report_iter->second;
-							LLViewerObject* avatarp = gObjectList.findObject(target_agent_id);
-							if (avatarp && 
-								avatarp->isAvatar() &&
-								agent_info_map.isMap())
-							{	// Extract the data for this avatar
-
-								if (LLAvatarRenderInfoAccountant::logRenderInfo())
-								{
-									LL_INFOS() << "LRI:  Agent " << target_agent_id 
-										<< ": " << agent_info_map << LL_ENDL;
-								}
-
-								if (agent_info_map.has(KEY_WEIGHT))
-								{
-									((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger());
-								}
-							}
-							report_iter++;
-						}
-					}
-				}	// has "agents"
-				else if (content.has(KEY_ERROR))
-				{
-					const LLSD & error = content[KEY_ERROR];
-					LL_WARNS() << "Avatar render info GET error: "
-						<< error[KEY_IDENTIFIER]
-						<< ": " << error[KEY_MESSAGE] 
-						<< " from region " << regionp->getName()
-						<< LL_ENDL;
-				}
-			}
-		}
-		else
-		{
-			LL_INFOS() << "Avatar render weight info recieved but region not found for " 
-				<< mRegionHandle << LL_ENDL;
-		}
-	}
-
-private:
-	U64		mRegionHandle;
-};
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t 
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    if (!regionp)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for " 
+                << regionHandle << LL_ENDL;
+        return;
+    }
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL;
+        return;
+    }
+
+    if (result.has(KEY_AGENTS))
+    {
+        const LLSD & agents = result[KEY_AGENTS];
+        if (agents.isMap())
+        {
+            LLSD::map_const_iterator	report_iter = agents.beginMap();
+            while (report_iter != agents.endMap())
+            {
+                LLUUID target_agent_id = LLUUID(report_iter->first);
+                const LLSD & agent_info_map = report_iter->second;
+                LLViewerObject* avatarp = gObjectList.findObject(target_agent_id);
+                if (avatarp && 
+                    avatarp->isAvatar() &&
+                    agent_info_map.isMap())
+                {	// Extract the data for this avatar
+
+                    if (LLAvatarRenderInfoAccountant::logRenderInfo())
+                    {
+                        LL_INFOS() << "LRI:  Agent " << target_agent_id 
+                            << ": " << agent_info_map << LL_ENDL;
+                    }
+
+                    if (agent_info_map.has(KEY_WEIGHT))
+                    {
+                        ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger());
+                    }
+                }
+                report_iter++;
+            }
+        }
+    }	// has "agents"
+    else if (result.has(KEY_ERROR))
+    {
+        const LLSD & error = result[KEY_ERROR];
+        LL_WARNS() << "Avatar render info GET error: "
+            << error[KEY_IDENTIFIER]
+            << ": " << error[KEY_MESSAGE] 
+            << " from region " << regionp->getName()
+            << LL_ENDL;
+    }
 
+}
 
-// HTTP responder class for POST request for avatar render weight information
-class LLAvatarRenderInfoPostResponder : public LLHTTPClient::Responder
+//-------------------------------------------------------------------------
+void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U64 regionHandle)
 {
-public:
-	LLAvatarRenderInfoPostResponder(U64 region_handle) : mRegionHandle(region_handle)
-	{
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    if (!regionp)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but region not found for "
+            << regionHandle << LL_ENDL;
+        return;
+    }
+
+    if (logRenderInfo())
+    {
+        LL_INFOS("AvatarRenderInfoAccountant") << "LRI: Sending avatar render info to region " << regionp->getName()
+                << " from " << url << LL_ENDL;
+    }
+
+    // Build the render info to POST to the region
+    LLSD report = LLSD::emptyMap();
+    LLSD agents = LLSD::emptyMap();
+
+    std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+    while( iter != LLCharacter::sInstances.end() )
+    {
+        LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter);
+        if (avatar &&
+            avatar->getRezzedStatus() >= 2 &&					// Mostly rezzed (maybe without baked textures downloaded)
+            !avatar->isDead() &&								// Not dead yet
+            avatar->getObjectHost() == regionp->getHost())		// Ensure it's on the same region
+        {
+            avatar->calculateUpdateRenderCost();			// Make sure the numbers are up-to-date
+
+            LLSD info = LLSD::emptyMap();
+            if (avatar->getVisualComplexity() > 0)
+            {
+                info[KEY_WEIGHT] = avatar->getVisualComplexity();
+                agents[avatar->getID().asString()] = info;
+
+                if (logRenderInfo())
+                {
+                    LL_INFOS("AvatarRenderInfoAccountant") << "LRI: Sending avatar render info for " << avatar->getID()
+                            << ": " << info << LL_ENDL;
+                    LL_INFOS("AvatarRenderInfoAccountant") << "LRI: other info geometry " << avatar->getAttachmentGeometryBytes()
+                            << ", area " << avatar->getAttachmentSurfaceArea()
+                            << LL_ENDL;
+                }
+            }
+        }
+        iter++;
+    }
+
+    if (agents.size() == 0)
+        return;
+
+    report[KEY_AGENTS] = agents;
+    regionp = NULL;
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report);
+
+    regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    if (!regionp)
+    {
+        LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for "
+                << regionHandle << LL_ENDL;
+        return;
+    }
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    if (!status)
+    {
+        LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL;
+        return;
+    }
+
+    if (LLAvatarRenderInfoAccountant::logRenderInfo())
+    {
+        LL_INFOS("AvatarRenderInfoAccountant") << "LRI: Result for avatar weights POST for region " << regionp->getName()
+            << ": " << result << LL_ENDL;
+    }
+
+    if (result.isMap())
+    {
+        if (result.has(KEY_ERROR))
+        {
+            const LLSD & error = result[KEY_ERROR];
+            LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render info POST error: "
+                << error[KEY_IDENTIFIER]
+                << ": " << error[KEY_MESSAGE] 
+                << " from region " << regionp->getName()
+                << LL_ENDL;
+        }
+    }
 
-	virtual void error(U32 statusNum, const std::string& reason)
-	{
-		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if (regionp)
-		{
-			LL_WARNS() << "HTTP error result for avatar weight POST: " << statusNum 
-				<< ", " << reason
-				<< " returned by region " << regionp->getName()
-				<< LL_ENDL;
-		}
-		else
-		{
-			LL_WARNS() << "Avatar render weight POST error recieved but region not found for " 
-				<< mRegionHandle 
-				<< ", error " << statusNum 
-				<< ", " << reason
-				<< LL_ENDL;
-		}
-	}
-
-	virtual void result(const LLSD& content)
-	{
-		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if (regionp)
-		{
-			if (LLAvatarRenderInfoAccountant::logRenderInfo())
-			{
-				LL_INFOS() << "LRI: Result for avatar weights POST for region " << regionp->getName()
-					<< ": " << content << LL_ENDL;
-			}
-
-			if (content.isMap())
-			{
-				if (content.has(KEY_ERROR))
-				{
-					const LLSD & error = content[KEY_ERROR];
-					LL_WARNS() << "Avatar render info POST error: "
-						<< error[KEY_IDENTIFIER]
-						<< ": " << error[KEY_MESSAGE] 
-						<< " from region " << regionp->getName()
-						<< LL_ENDL;
-				}
-			}
-		}
-		else
-		{
-			LL_INFOS() << "Avatar render weight POST result recieved but region not found for " 
-				<< mRegionHandle << LL_ENDL;
-		}
-	}
-
-private:
-	U64		mRegionHandle;
-};
 
+}
 
 // static 
 // Send request for one region, no timer checks
@@ -223,53 +237,9 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio
 	std::string url = regionp->getCapability("AvatarRenderInfo");
 	if (!url.empty())
 	{
-		if (logRenderInfo())
-		{
-			LL_INFOS() << "LRI: Sending avatar render info to region "
-				<< regionp->getName() 
-				<< " from " << url
-				<< LL_ENDL;
-		}
-
-		// Build the render info to POST to the region
-		LLSD report = LLSD::emptyMap();
-		LLSD agents = LLSD::emptyMap();
-				
-		std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
-		while( iter != LLCharacter::sInstances.end() )
-		{
-			LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter);
-			if (avatar &&
-				avatar->getRezzedStatus() >= 2 &&					// Mostly rezzed (maybe without baked textures downloaded)
-				!avatar->isDead() &&								// Not dead yet
-				avatar->getObjectHost() == regionp->getHost())		// Ensure it's on the same region
-			{
-				avatar->calculateUpdateRenderCost();			// Make sure the numbers are up-to-date
-
-				LLSD info = LLSD::emptyMap();
-				if (avatar->getVisualComplexity() > 0)
-				{
-					info[KEY_WEIGHT] = avatar->getVisualComplexity();
-					agents[avatar->getID().asString()] = info;
-
-					if (logRenderInfo())
-					{
-						LL_INFOS() << "LRI: Sending avatar render info for " << avatar->getID()
-							<< ": " << info << LL_ENDL;
-						LL_INFOS() << "LRI: other info geometry " << avatar->getAttachmentGeometryBytes()
-							<< ", area " << avatar->getAttachmentSurfaceArea()
-							<< LL_ENDL;
-					}
-				}
-			}
-			iter++;
-		}
-
-		report[KEY_AGENTS] = agents;
-		if (agents.size() > 0)
-		{
-			LLHTTPClient::post(url, report, new LLAvatarRenderInfoPostResponder(regionp->getHandle()));
-		}
+        std::string coroname =
+            LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro",
+            boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro, url, regionp->getHandle()));
 	}
 }
 
@@ -292,7 +262,9 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
 		}
 
 		// First send a request to get the latest data
-		LLHTTPClient::get(url, new LLAvatarRenderInfoGetResponder(regionp->getHandle()));
+        std::string coroname =
+            LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro",
+            boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro, url, regionp->getHandle()));
 	}
 }
 
@@ -301,6 +273,9 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
 // Called every frame - send render weight requests to every region
 void LLAvatarRenderInfoAccountant::idle()
 {
+//	if (!LLAvatarRenderInfoAccountant::sHttpRequest)
+//		sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+
 	if (sRenderInfoReportTimer.hasExpired())
 	{
 		const F32 SECS_BETWEEN_REGION_SCANS   =  5.f;		// Scan the region list every 5 seconds
@@ -393,6 +368,7 @@ void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer(const LLUUID& reg
 // static 
 bool LLAvatarRenderInfoAccountant::logRenderInfo()
 {
-	static LLCachedControl<bool> render_mute_logging_enabled(gSavedSettings, "RenderAutoMuteLogging", false);
-	return render_mute_logging_enabled;
+    return true;
+// 	static LLCachedControl<bool> render_mute_logging_enabled(gSavedSettings, "RenderAutoMuteLogging", false);
+// 	return render_mute_logging_enabled;
 }
diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h
index d68f2dccfbdd8f7cb140bf54ec328c769c5d1aaa..f7a04cca2c214922548b8bb45fb2303bfff6dfc2 100644
--- a/indra/newview/llavatarrenderinfoaccountant.h
+++ b/indra/newview/llavatarrenderinfoaccountant.h
@@ -29,6 +29,9 @@
 #if ! defined(LL_llavatarrenderinfoaccountant_H)
 #define LL_llavatarrenderinfoaccountant_H
 
+#include "httpcommon.h"
+#include "llcoros.h"
+
 class LLViewerRegion;
 
 // Class to gather avatar rendering information 
@@ -36,8 +39,6 @@ class LLViewerRegion;
 class LLAvatarRenderInfoAccountant
 {
 public:
-	LLAvatarRenderInfoAccountant()	{};
-	~LLAvatarRenderInfoAccountant()	{};
 
 	static void sendRenderInfoToRegion(LLViewerRegion * regionp);
 	static void getRenderInfoFromRegion(LLViewerRegion * regionp);
@@ -49,8 +50,16 @@ class LLAvatarRenderInfoAccountant
 	static bool logRenderInfo();
 
 private:
+	LLAvatarRenderInfoAccountant() {};
+	~LLAvatarRenderInfoAccountant()	{};
+
 	// Send data updates about once per minute, only need per-frame resolution
 	static LLFrameTimer sRenderInfoReportTimer;
+
+    static void avatarRenderInfoGetCoro(std::string url, U64 regionHandle);
+    static void avatarRenderInfoReportCoro(std::string url, U64 regionHandle);
+
+
 };
 
 #endif /* ! defined(LL_llavatarrenderinfoaccountant_H) */
diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp
old mode 100755
new mode 100644
diff --git a/indra/newview/llcapabilitylistener.cpp b/indra/newview/llcapabilitylistener.cpp
deleted file mode 100755
index ef9b910ae5fcf1dfe0b553f95bddd145ce08b047..0000000000000000000000000000000000000000
--- a/indra/newview/llcapabilitylistener.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * @file   llcapabilitylistener.cpp
- * @author Nat Goodspeed
- * @date   2009-01-07
- * @brief  Implementation for llcapabilitylistener.
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "llviewerprecompiledheaders.h"
-// associated header
-#include "llcapabilitylistener.h"
-// STL headers
-#include <map>
-// std headers
-// external library headers
-#include <boost/bind.hpp>
-// other Linden headers
-#include "stringize.h"
-#include "llcapabilityprovider.h"
-#include "message.h"
-
-class LLCapabilityListener::CapabilityMappers: public LLSingleton<LLCapabilityListener::CapabilityMappers>
-{
-public:
-    void registerMapper(const LLCapabilityListener::CapabilityMapper*);
-    void unregisterMapper(const LLCapabilityListener::CapabilityMapper*);
-    const LLCapabilityListener::CapabilityMapper* find(const std::string& cap) const;
-
-    struct DupCapMapper: public std::runtime_error
-    {
-        DupCapMapper(const std::string& what):
-            std::runtime_error(std::string("DupCapMapper: ") + what)
-        {}
-    };
-
-private:
-    friend class LLSingleton<LLCapabilityListener::CapabilityMappers>;
-    CapabilityMappers();
-
-    typedef std::map<std::string, const LLCapabilityListener::CapabilityMapper*> CapabilityMap;
-    CapabilityMap mMap;
-};
-
-LLCapabilityListener::LLCapabilityListener(const std::string& name,
-                                           LLMessageSystem* messageSystem,
-                                           const LLCapabilityProvider& provider,
-                                           const LLUUID& agentID,
-                                           const LLUUID& sessionID):
-    mEventPump(name),
-    mMessageSystem(messageSystem),
-    mProvider(provider),
-    mAgentID(agentID),
-    mSessionID(sessionID)
-{
-    mEventPump.listen("self", boost::bind(&LLCapabilityListener::capListener, this, _1));
-}
-
-bool LLCapabilityListener::capListener(const LLSD& request)
-{
-    // Extract what we want from the request object. We do it all up front
-    // partly to document what we expect.
-    LLSD::String cap(request["message"]);
-    LLSD payload(request["payload"]);
-    LLSD::String reply(request["reply"]);
-    LLSD::String error(request["error"]);
-    LLSD::Real timeout(request["timeout"]);
-    // If the LLSD doesn't even have a "message" key, we doubt it was intended
-    // for this listener.
-    if (cap.empty())
-    {
-        LL_ERRS("capListener") << "capability request event without 'message' key to '"
-                               << getCapAPI().getName()
-                               << "' on region\n" << mProvider.getDescription()
-                               << LL_ENDL;
-        return false;               // in case fatal-error function isn't
-    }
-    // Establish default timeout. This test relies on LLSD::asReal() returning
-    // exactly 0.0 for an undef value.
-    if (! timeout)
-    {
-        timeout = HTTP_REQUEST_EXPIRY_SECS;
-    }
-    // Look up the url for the requested capability name.
-    std::string url = mProvider.getCapability(cap);
-    if (! url.empty())
-    {
-        // This capability is supported by the region to which we're talking.
-        LLHTTPClient::post(url, payload,
-                           new LLSDMessage::EventResponder(LLEventPumps::instance(),
-                                                           request,
-                                                           mProvider.getDescription(),
-                                                           cap, reply, error),
-                           LLSD(),  // headers
-                           timeout);
-    }
-    else
-    {
-        // Capability not supported -- do we have a registered mapper?
-        const CapabilityMapper* mapper = CapabilityMappers::instance().find(cap);
-        if (! mapper)               // capability neither supported nor mapped
-        {
-            LL_ERRS("capListener") << "unsupported capability '" << cap << "' request to '"
-                                   << getCapAPI().getName() << "' on region\n"
-                                   << mProvider.getDescription()
-                                   << LL_ENDL;
-        }
-        else if (! mapper->getReplyName().empty()) // mapper expects reply support
-        {
-            LL_ERRS("capListener") << "Mapper for capability '" << cap
-                                   << "' requires unimplemented support for reply message '"
-                                   << mapper->getReplyName()
-                                   << "' on '" << getCapAPI().getName() << "' on region\n"
-                                   << mProvider.getDescription()
-                                   << LL_ENDL;
-        }
-        else
-        {
-            LL_INFOS("capListener") << "fallback invoked for capability '" << cap
-                                    << "' request to '" << getCapAPI().getName()
-                                    << "' on region\n" << mProvider.getDescription()
-                                    << LL_ENDL;
-            mapper->buildMessage(mMessageSystem, mAgentID, mSessionID, cap, payload);
-            mMessageSystem->sendReliable(mProvider.getHost());
-        }
-    }
-    return false;
-}
-
-LLCapabilityListener::CapabilityMapper::CapabilityMapper(const std::string& cap, const std::string& reply):
-    mCapName(cap),
-    mReplyName(reply)
-{
-    LLCapabilityListener::CapabilityMappers::instance().registerMapper(this);
-}
-
-LLCapabilityListener::CapabilityMapper::~CapabilityMapper()
-{
-    LLCapabilityListener::CapabilityMappers::instance().unregisterMapper(this);
-}
-
-LLSD LLCapabilityListener::CapabilityMapper::readResponse(LLMessageSystem* messageSystem) const
-{
-    return LLSD();
-}
-
-LLCapabilityListener::CapabilityMappers::CapabilityMappers() {}
-
-void LLCapabilityListener::CapabilityMappers::registerMapper(const LLCapabilityListener::CapabilityMapper* mapper)
-{
-    // Try to insert a new map entry by which we can look up the passed mapper
-    // instance.
-    std::pair<CapabilityMap::iterator, bool> inserted =
-        mMap.insert(CapabilityMap::value_type(mapper->getCapName(), mapper));
-    // If we already have a mapper for that name, insert() merely located the
-    // existing iterator and returned false. It is a coding error to try to
-    // register more than one mapper for the same capability name.
-    if (! inserted.second)
-    {
-        throw DupCapMapper(std::string("Duplicate capability name ") + mapper->getCapName());
-    }
-}
-
-void LLCapabilityListener::CapabilityMappers::unregisterMapper(const LLCapabilityListener::CapabilityMapper* mapper)
-{
-    CapabilityMap::iterator found = mMap.find(mapper->getCapName());
-    if (found != mMap.end())
-    {
-        mMap.erase(found);
-    }
-}
-
-const LLCapabilityListener::CapabilityMapper*
-LLCapabilityListener::CapabilityMappers::find(const std::string& cap) const
-{
-    CapabilityMap::const_iterator found = mMap.find(cap);
-    if (found != mMap.end())
-    {
-        return found->second;
-    }
-    return NULL;
-}
diff --git a/indra/newview/llcapabilitylistener.h b/indra/newview/llcapabilitylistener.h
deleted file mode 100755
index e7535013e7bacba29db361e09df5a0753e0cfd57..0000000000000000000000000000000000000000
--- a/indra/newview/llcapabilitylistener.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
- * @file   llcapabilitylistener.h
- * @author Nat Goodspeed
- * @date   2009-01-07
- * @brief  Provide an event-based API for capability requests
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLCAPABILITYLISTENER_H)
-#define LL_LLCAPABILITYLISTENER_H
-
-#include "llevents.h"               // LLEventPump
-#include "llsdmessage.h"            // LLSDMessage::ArgError
-#include "llerror.h"                // LOG_CLASS()
-
-class LLCapabilityProvider;
-class LLMessageSystem;
-class LLSD;
-
-class LLCapabilityListener
-{
-    LOG_CLASS(LLCapabilityListener);
-public:
-    LLCapabilityListener(const std::string& name, LLMessageSystem* messageSystem,
-                         const LLCapabilityProvider& provider,
-                         const LLUUID& agentID, const LLUUID& sessionID);
-
-    /// Capability-request exception
-    typedef LLSDMessage::ArgError ArgError;
-    /// Get LLEventPump on which we listen for capability requests
-    /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-    LLEventPump& getCapAPI() { return mEventPump; }
-
-    /**
-     * Base class for mapping an as-yet-undeployed capability name to a (pair
-     * of) LLMessageSystem message(s). To map a capability name to such
-     * messages, derive a subclass of CapabilityMapper and declare a static
-     * instance in a translation unit known to be loaded. The mapping is not
-     * region-specific. If an LLViewerRegion's capListener() receives a
-     * request for a supported capability, it will use the capability's URL.
-     * If not, it will look for an applicable CapabilityMapper subclass
-     * instance.
-     */
-    class CapabilityMapper
-    {
-    public:
-        /**
-         * Base-class constructor. Typically your subclass constructor will
-         * pass these parameters as literals.
-         * @param cap the capability name handled by this (subclass) instance
-         * @param reply the name of the response LLMessageSystem message. Omit
-         * if the LLMessageSystem message you intend to send doesn't prompt a
-         * reply message, or if you already handle that message in some other
-         * way.
-         */
-        CapabilityMapper(const std::string& cap, const std::string& reply = "");
-        virtual ~CapabilityMapper();
-        /// query the capability name
-        std::string getCapName() const { return mCapName; }
-        /// query the reply message name
-        std::string getReplyName() const { return mReplyName; }
-        /**
-         * Override this method to build the LLMessageSystem message we should
-         * send instead of the requested capability message. DO NOT send that
-         * message: that will be handled by the caller.
-         */
-        virtual void buildMessage(LLMessageSystem* messageSystem,
-                                  const LLUUID& agentID,
-                                  const LLUUID& sessionID,
-                                  const std::string& capabilityName,
-                                  const LLSD& payload) const = 0;
-        /**
-         * Override this method if you pass a non-empty @a reply
-         * LLMessageSystem message name to the constructor: that is, if you
-         * expect to receive an LLMessageSystem message in response to the
-         * message you constructed in buildMessage(). If you don't pass a @a
-         * reply message name, you need not override this method as it won't
-         * be called.
-         *
-         * Using LLMessageSystem message-reading operations, your
-         * readResponse() override should construct and return an LLSD object
-         * of the form you expect to receive from the real implementation of
-         * the capability you intend to invoke, when it finally goes live.
-         */
-        virtual LLSD readResponse(LLMessageSystem* messageSystem) const;
-
-    private:
-        const std::string mCapName;
-        const std::string mReplyName;
-    };
-
-private:
-    /// Bind the LLCapabilityProvider passed to our ctor
-    const LLCapabilityProvider& mProvider;
-
-    /// Post an event to this LLEventPump to invoke a capability message on
-    /// the bound LLCapabilityProvider's server
-    /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-    LLEventStream mEventPump;
-
-    LLMessageSystem* mMessageSystem;
-    LLUUID mAgentID, mSessionID;
-
-    /// listener to process capability requests
-    bool capListener(const LLSD&);
-
-    /// helper class for capListener()
-    class CapabilityMappers;
-};
-
-#endif /* ! defined(LL_LLCAPABILITYLISTENER_H) */
diff --git a/indra/newview/llcaphttpsender.cpp b/indra/newview/llcaphttpsender.cpp
deleted file mode 100755
index b2524d14f8fa26793e1d7a3857b31a8c2e856f6c..0000000000000000000000000000000000000000
--- a/indra/newview/llcaphttpsender.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/** 
- * @file llcaphttpsender.cpp
- * @brief Abstracts details of sending messages via UntrustedMessage cap.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llcaphttpsender.h"
-
-#include "llhost.h"
-
-LLCapHTTPSender::LLCapHTTPSender(const std::string& cap) :
-	mCap(cap)
-{
-}
-
-//virtual 
-void LLCapHTTPSender::send(const LLHost& host, const std::string& message, 
-								  const LLSD& body, 
-								  LLHTTPClient::ResponderPtr response) const
-{
-	LL_INFOS() << "LLCapHTTPSender::send: message " << message
-			<< " to host " << host << LL_ENDL;
-	LLSD llsd;
-	llsd["message"] = message;
-	llsd["body"] = body;
-	LLHTTPClient::post(mCap, llsd, response);
-}
diff --git a/indra/newview/llcaphttpsender.h b/indra/newview/llcaphttpsender.h
deleted file mode 100755
index e1f4c813f6d3be6ec3a59213b17483952e700047..0000000000000000000000000000000000000000
--- a/indra/newview/llcaphttpsender.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/** 
- * @file llcaphttpsender.h
- * @brief Abstracts details of sending messages via the
- *        UntrustedMessage capability.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_CAP_HTTP_SENDER_H
-#define LL_CAP_HTTP_SENDER_H
-
-#include "llhttpsender.h"
-
-class LLCapHTTPSender : public LLHTTPSender
-{
-public:
-	LLCapHTTPSender(const std::string& cap);
-
-	/** @brief Send message via UntrustedMessage capability with body,
-		call response when done */ 
-	virtual void send(const LLHost& host, 
-					  const std::string& message, const LLSD& body, 
-					  LLHTTPClient::ResponderPtr response) const;
-
-private:
-	std::string mCap;
-};
-
-#endif // LL_CAP_HTTP_SENDER_H
diff --git a/indra/newview/llclassifiedstatsresponder.cpp b/indra/newview/llclassifiedstatsresponder.cpp
deleted file mode 100755
index f1ef8e9a035a404a881fa93d156649909d2fdb02..0000000000000000000000000000000000000000
--- a/indra/newview/llclassifiedstatsresponder.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/** 
- * @file llclassifiedstatsresponder.cpp
- * @brief Receives information about classified ad click-through
- * counts for display in the classified information UI.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llclassifiedstatsresponder.h"
-
-#include "llpanelclassified.h"
-#include "llpanel.h"
-#include "llhttpclient.h"
-#include "llsdserialize.h"
-#include "llviewerregion.h"
-#include "llview.h"
-#include "message.h"
-
-LLClassifiedStatsResponder::LLClassifiedStatsResponder(LLUUID classified_id)
-:	mClassifiedID(classified_id)
-{}
-
-/*virtual*/
-void LLClassifiedStatsResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	S32 teleport = content["teleport_clicks"].asInteger();
-	S32 map = content["map_clicks"].asInteger();
-	S32 profile = content["profile_clicks"].asInteger();
-	S32 search_teleport = content["search_teleport_clicks"].asInteger();
-	S32 search_map = content["search_map_clicks"].asInteger();
-	S32 search_profile = content["search_profile_clicks"].asInteger();
-
-	LLPanelClassifiedInfo::setClickThrough(	mClassifiedID, 
-											teleport + search_teleport, 
-											map + search_map,
-											profile + search_profile,
-											true);
-}
-
-/*virtual*/
-void LLClassifiedStatsResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-}
-
diff --git a/indra/newview/llclassifiedstatsresponder.h b/indra/newview/llclassifiedstatsresponder.h
deleted file mode 100755
index efa4d82411d2df7dd4d598476a02ef107ed206d9..0000000000000000000000000000000000000000
--- a/indra/newview/llclassifiedstatsresponder.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/** 
- * @file llclassifiedstatsresponder.h
- * @brief Receives information about classified ad click-through
- * counts for display in the classified information UI.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLCLASSIFIEDSTATSRESPONDER_H
-#define LL_LLCLASSIFIEDSTATSRESPONDER_H
-
-#include "llhttpclient.h"
-#include "llview.h"
-#include "lluuid.h"
-
-class LLClassifiedStatsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLClassifiedStatsResponder);
-public:
-	LLClassifiedStatsResponder(LLUUID classified_id);
-
-protected:
-	//If we get back a normal response, handle it here
-	virtual void httpSuccess();
-	//If we get back an error (not found, etc...), handle it here
-	virtual void httpFailure();
-
-protected:
-	LLUUID mClassifiedID;
-};
-
-#endif // LL_LLCLASSIFIEDSTATSRESPONDER_H
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 19dba3f9173a0a210736d92f620a96f5ad6283c7..5ea7efc0454dbd26281f9d4bace2bf44dbbdd28e 100755
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -30,6 +30,7 @@
 #include "llcommandhandler.h"
 #include "llnotificationsutil.h"
 #include "llcommanddispatcherlistener.h"
+#include "llstartup.h"
 #include "stringize.h"
 
 // system includes
@@ -116,7 +117,11 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 			LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
 			if (! slurl_blocked)
 			{
-				LLNotificationsUtil::add("BlockedSLURL");
+				if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+				{
+					// Note: commands can arrive before we initialize everything we need for Notification.
+					LLNotificationsUtil::add("BlockedSLURL");
+				}
 				slurl_blocked = true;
 			}
 			return true;
@@ -138,7 +143,10 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
 				LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
 				if (! slurl_throttled)
 				{
-					LLNotificationsUtil::add("ThrottledSLURL");
+					if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+					{
+						LLNotificationsUtil::add("ThrottledSLURL");
+					}
 					slurl_throttled = true;
 				}
 				return true;
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index d9fd4509a5993d3f76df243a9455096f8f379146..219bcf0eb03b0da021bcac4bb7c6329b034bf243 100755
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -37,8 +37,6 @@
 #include "llcompilequeue.h"
 
 #include "llagent.h"
-#include "llassetuploadqueue.h"
-#include "llassetuploadresponders.h"
 #include "llchat.h"
 #include "llfloaterreg.h"
 #include "llviewerwindow.h"
@@ -59,11 +57,54 @@
 #include "lltrans.h"
 
 #include "llselectmgr.h"
-#include "llexperienceassociationresponder.h"
 #include "llexperiencecache.h"
 
-// *TODO: This should be separated into the script queue, and the floater views of that queue.
-// There should only be one floater class that can view any queue type
+#include "llviewerassetupload.h"
+#include "llcorehttputil.h"
+
+// *NOTE$: A minor specialization of LLScriptAssetUpload, it does not require a buffer 
+// (and does not save a buffer to the vFS) and it finds the compile queue window and 
+// displays a compiling message.
+class LLQueuedScriptAssetUpload : public LLScriptAssetUpload
+{
+public:
+    LLQueuedScriptAssetUpload(LLUUID taskId, LLUUID itemId, LLUUID assetId, TargetType_t targetType,
+            bool isRunning, std::string scriptName, LLUUID queueId, LLUUID exerienceId, taskUploadFinish_f finish) :
+        LLScriptAssetUpload(taskId, itemId, targetType, isRunning, 
+            exerienceId, std::string(), finish),
+        mScriptName(scriptName),
+        mQueueId(queueId)
+    {
+        setAssetId(assetId);
+    }
+
+    virtual LLSD prepareUpload()
+    {
+        /* *NOTE$: The parent class (LLScriptAssetUpload will attempt to save 
+         * the script buffer into to the VFS.  Since the resource is already in 
+         * the VFS we don't want to do that.  Just put a compiling message in
+         * the window and move on
+         */
+        LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
+        if (queue)
+        {
+            std::string message = std::string("Compiling \"") + getScriptName() + std::string("\"...");
+
+            queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
+        }
+
+        return LLSD().with("success", LLSD::Boolean(true));
+    }
+
+
+    std::string getScriptName() const { return mScriptName; }
+
+private:
+    void setScriptName(const std::string &scriptName) { mScriptName = scriptName; }
+
+    LLUUID mQueueId;
+    std::string mScriptName;
+};
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
@@ -127,7 +168,7 @@ void LLFloaterScriptQueue::inventoryChanged(LLViewerObject* viewer_object,
 	//which it internally stores.
 	
 	//If we call this further down in the function, calls to handleInventory
-	//and nextObject may update the interally stored viewer object causing
+	//and nextObject may update the internally stored viewer object causing
 	//the removal of the incorrect listener from an incorrect object.
 	
 	//Fixes SL-6119:Recompile scripts fails to complete
@@ -242,81 +283,17 @@ BOOL LLFloaterScriptQueue::startQueue()
 	return nextObject();
 }
 
-class CompileQueueExperienceResponder : public LLHTTPClient::Responder
-{
-public:
-	CompileQueueExperienceResponder(const LLUUID& parent):mParent(parent)
-	{
-	}
-
-	LLUUID mParent;
-
-	/*virtual*/ void httpSuccess()
-	{	
-		sendResult(getContent());
-	}
-	/*virtual*/ void httpFailure()
-	{
-		sendResult(LLSD());
-	}
-	void sendResult(const LLSD& content)
-	{
-		LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mParent);
-		if(!queue)
-			return;
-
-		queue->experienceIdsReceived(content["experience_ids"]);	
-	}
-};
-
-
-
 
 ///----------------------------------------------------------------------------
 /// Class LLFloaterCompileQueue
 ///----------------------------------------------------------------------------
-
-class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier
-{
-public:
-	
-	LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) :
-		mQueueId(queue_id)
-	{
-	}
-		
-	virtual LLAssetUploadQueue* get() const 
-	{
-		LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
-		if(NULL == queue)
-		{
-			return NULL;
-		}
-		return queue->getUploadQueue();
-	}
-
-	virtual void log(std::string message) const
-	{
-		LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
-		if(NULL == queue)
-		{
-			return;
-		}
-
-		queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
-	}
-		
-private:
-	LLUUID mQueueId;
-};
-
 LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key)
   : LLFloaterScriptQueue(key)
 {
 	setTitle(LLTrans::getString("CompileQueueTitle"));
 	setStartString(LLTrans::getString("CompileQueueStart"));
 														 															 
-	mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
+//	mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
 }
 
 LLFloaterCompileQueue::~LLFloaterCompileQueue()
@@ -380,8 +357,8 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
 			LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
 				viewer_object->getID(), itemp);
 
-			ExperienceAssociationResponder::fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), 
-				boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1));
+            LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
+                    boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1));
 		}
 	}
 }
@@ -423,6 +400,37 @@ void LLFloaterCompileQueue::requestAsset( LLScriptQueueData* datap, const LLSD&
 		(void*)datap);
 }
 
+/*static*/
+void LLFloaterCompileQueue::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId)
+{
+
+    LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(queueId));
+    if (queue)
+    {
+        // Bytecode save completed
+        if (response["compiled"])
+        {
+            std::string message = std::string("Compilation of \"") + scriptName + std::string("\" succeeded");
+
+            queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
+            LL_INFOS() << message << LL_ENDL;
+        }
+        else
+        {
+            LLSD compile_errors = response["errors"];
+            for (LLSD::array_const_iterator line = compile_errors.beginArray();
+                line < compile_errors.endArray(); line++)
+            {
+                std::string str = line->asString();
+                str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
+
+                queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(str, ADD_BOTTOM);
+            }
+            LL_INFOS() << response["errors"] << LL_ENDL;
+        }
+
+    }
+}
 
 // This is the callback for when each script arrives
 // static
@@ -441,36 +449,21 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
 	std::string buffer;
 	if(queue && (0 == status))
 	{
-		//LL_INFOS() << "ITEM NAME 3: " << data->mScriptName << LL_ENDL;
-
-		// Dump this into a file on the local disk so we can compile it.
-		std::string filename;
-		LLVFile file(vfs, asset_id, type);
-		std::string uuid_str;
-		asset_id.toString(uuid_str);
-		filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + llformat(".%s",LLAssetType::lookup(type));
-		
-		const bool is_running = true;
-		LLViewerObject* object = gObjectList.findObject(data->mTaskId);
-		if (object)
-		{
-			std::string url = object->getRegion()->getCapability("UpdateScriptTask");
-			if(!url.empty())
-			{
-				// Read script source in to buffer.
-				U32 script_size = file.getSize();
-				U8* script_data = new U8[script_size];
-				file.read(script_data, script_size);
-
-				queue->mUploadQueue->queue(filename, data->mTaskId, 
-										   data->mItem->getUUID(), is_running, queue->mMono, queue->getKey().asUUID(),
-										   script_data, script_size, data->mItem->getName(), data->mExperienceId);
-			}
-			else
-			{
-				buffer = LLTrans::getString("CompileQueueServiceUnavailable") + (": ") + data->mItem->getName();
-			}
-		}
+        LLViewerObject* object = gObjectList.findObject(data->mTaskId);
+        if (object)
+        {
+            std::string url = object->getRegion()->getCapability("UpdateScriptTask");
+            std::string scriptName = data->mItem->getName();
+
+            LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLFloaterCompileQueue::finishLSLUpload, _1, _2, _3, _4, 
+                scriptName, data->mQueueID);
+
+            LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(data->mTaskId, data->mItem->getUUID(), asset_id,
+                (queue->mMono) ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2,
+                true, scriptName, data->mQueueID, data->mExperienceId, proc));
+
+            LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+        }
 	}
 	else
 	{
@@ -653,14 +646,29 @@ BOOL LLFloaterCompileQueue::startQueue()
 		std::string lookup_url=region->getCapability("GetCreatorExperiences"); 
 		if(!lookup_url.empty())
 		{
-			LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(getKey().asUUID()));
-			return TRUE;
+            LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success =
+                boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID());
+
+            LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure =
+                boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID());
+
+            LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url,
+                success, failure);
+            return TRUE;
 		}
 	}
 	return nextObject();
 }
 
+/*static*/
+void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent)
+{
+    LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent);
+    if (!queue)
+        return;
 
+    queue->experienceIdsReceived(result["experience_ids"]);
+}
 
 void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
 										  LLInventoryObject::object_list_t* inv)
diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h
index 54842bb3023c9104b158d8172d505bbd9732ec0f..cee8efe9b0a3e0ef0d2007f7cccca7f5584c0b3f 100755
--- a/indra/newview/llcompilequeue.h
+++ b/indra/newview/llcompilequeue.h
@@ -118,8 +118,6 @@ struct LLCompileQueueData
 		mQueueID(q_id), mItemId(item_id) {}
 };
 
-class LLAssetUploadQueue;
-
 class LLFloaterCompileQueue : public LLFloaterScriptQueue
 {
 	friend class LLFloaterReg;
@@ -131,8 +129,6 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue
 	// remove any object in mScriptScripts with the matching uuid.
 	void removeItemByItemID(const LLUUID& item_id);
 	
-	LLAssetUploadQueue* getUploadQueue() { return mUploadQueue; }
-
 	void experienceIdsReceived( const LLSD& content );
 	BOOL hasExperience(const LLUUID& id)const;
 
@@ -147,6 +143,8 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue
 	static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience);
 
 
+    static void finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId);
+
 	// This is the callback for when each script arrives
 	static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
 								LLAssetType::EType type,
@@ -157,7 +155,8 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue
 	LLViewerInventoryItem::item_array_t mCurrentScripts;
 
 private:
-	LLAssetUploadQueue* mUploadQueue;
+    static void processExperienceIdResults(LLSD result, LLUUID parent);
+
 	uuid_list_t mExperienceIds;
 };
 
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 821d58a9b282c6fe41bf009905588418379224dc..f828b56f7f587099f82a574740acc58cf82c2485 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1600,6 +1600,14 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		for (U32 j = 0; j < count; ++j)
 		{
 			LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+			if (!joint)
+			{
+				joint = avatar->getJoint("mPelvis");
+			}
+			if (!joint)
+			{
+				LL_DEBUGS("Avatar") << "Failed to find " << skin->mJointNames[j] << LL_ENDL;
+			}
 			if (joint)
 			{
 				mat[j] = skin->mInvBindMatrix[j];
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 78d619a315b1a17f113a410c21c2d359c9fcc94d..8f2eb4130739680e1bfb75f015e6916427bca79b 100755
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -29,7 +29,6 @@
 #include "llestateinfomodel.h"
 
 // libs
-#include "llhttpclient.h"
 #include "llregionflags.h"
 #include "message.h"
 
@@ -38,6 +37,8 @@
 #include "llfloaterregioninfo.h" // for invoice id
 #include "llviewerregion.h"
 
+#include "llcorehttputil.h"
+
 LLEstateInfoModel::LLEstateInfoModel()
 :	mID(0)
 ,	mFlags(0)
@@ -110,24 +111,6 @@ void LLEstateInfoModel::notifyCommit()
 
 //== PRIVATE STUFF ============================================================
 
-class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLEstateChangeInfoResponder);
-protected:
-	// if we get a normal response, handle it here
-	virtual void httpSuccesss()
-	{
-		LL_INFOS() << "Committed estate info" << LL_ENDL;
-		LLEstateInfoModel::instance().notifyCommit();
-	}
-
-	// if we get an error response
-	virtual void httpFailure()
-	{
-		LL_WARNS() << "Failed to commit estate info " << dumpResponse() << LL_ENDL;
-	}
-};
-
 // tries to send estate info using a cap; returns true if it succeeded
 bool LLEstateInfoModel::commitEstateInfoCaps()
 {
@@ -139,29 +122,53 @@ bool LLEstateInfoModel::commitEstateInfoCaps()
 		return false;
 	}
 
-	LLSD body;
-	body["estate_name"          ] = getName();
-	body["sun_hour"             ] = getSunHour();
+    LLCoros::instance().launch("LLEstateInfoModel::commitEstateInfoCapsCoro",
+        boost::bind(&LLEstateInfoModel::commitEstateInfoCapsCoro, this, url));
 
-	body["is_sun_fixed"         ] = getUseFixedSun();
-	body["is_externally_visible"] = getIsExternallyVisible();
-	body["allow_direct_teleport"] = getAllowDirectTeleport();
-	body["deny_anonymous"       ] = getDenyAnonymous();
-	body["deny_age_unverified"  ] = getDenyAgeUnverified();
-	body["allow_voice_chat"     ] = getAllowVoiceChat();
-
-	body["invoice"              ] = LLFloaterRegionInfo::getLastInvoice();
-
-	LL_DEBUGS("Windlight Sync") << "Sending estate caps: "
-		<< "is_sun_fixed = " << getUseFixedSun()
-		<< ", sun_hour = " << getSunHour() << LL_ENDL;
-	LL_DEBUGS() << body << LL_ENDL;
-
-	// we use a responder so that we can re-get the data after committing to the database
-	LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder);
     return true;
 }
 
+void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EstateChangeInfo", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD body;
+    body["estate_name"] = getName();
+    body["sun_hour"] = getSunHour();
+
+    body["is_sun_fixed"] = getUseFixedSun();
+    body["is_externally_visible"] = getIsExternallyVisible();
+    body["allow_direct_teleport"] = getAllowDirectTeleport();
+    body["deny_anonymous"] = getDenyAnonymous();
+    body["deny_age_unverified"] = getDenyAgeUnverified();
+    body["allow_voice_chat"] = getAllowVoiceChat();
+
+    body["invoice"] = LLFloaterRegionInfo::getLastInvoice();
+
+    LL_DEBUGS("Windlight Sync") << "Sending estate caps: "
+        << "is_sun_fixed = " << getUseFixedSun()
+        << ", sun_hour = " << getSunHour() << LL_ENDL;
+    LL_DEBUGS() << body << LL_ENDL;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status)
+    {
+        LL_INFOS() << "Committed estate info" << LL_ENDL;
+        LLEstateInfoModel::instance().notifyCommit();
+    }
+    else
+    {
+        LL_WARNS() << "Failed to commit estate info " << LL_ENDL;
+    }
+}
+
 /* This is the old way of doing things, is deprecated, and should be
    deleted when the dataserver model can be removed */
 // key = "estatechangeinfo"
diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h
index 538f2f7c756f868fb58a6746da963974e6b40592..fcfbd1ce7db2c9c0abd88ae6c33353948ac52141 100755
--- a/indra/newview/llestateinfomodel.h
+++ b/indra/newview/llestateinfomodel.h
@@ -30,6 +30,8 @@
 class LLMessageSystem;
 
 #include "llsingleton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 /**
  * Contains estate info, notifies interested parties of its changes.
@@ -73,7 +75,6 @@ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
 
 	friend class LLSingleton<LLEstateInfoModel>;
 	friend class LLDispatchEstateUpdateInfo;
-	friend class LLEstateChangeInfoResponder;
 
 	LLEstateInfoModel();
 
@@ -99,6 +100,8 @@ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
 
 	update_signal_t mUpdateSignal; /// emitted when we receive update from sim
 	update_signal_t mCommitSignal; /// emitted when our update gets applied to sim
+
+    void commitEstateInfoCapsCoro(std::string url);
 };
 
 inline bool LLEstateInfoModel::getFlag(U64 flag) const
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 4de6ad4d2f4bc75bc89c3cbcc16d343710539216..021d17251d87d1374003cfd6a557fb3de8644809 100755
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -30,261 +30,248 @@
 #include "llappviewer.h"
 #include "llagent.h"
 
-#include "llhttpclient.h"
-#include "llhttpconstants.h"
 #include "llsdserialize.h"
 #include "lleventtimer.h"
 #include "llviewerregion.h"
 #include "message.h"
 #include "lltrans.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
+#include "lleventfilter.h"
 
-namespace
+namespace LLEventPolling
 {
-	// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
-	// This means we attempt to recover relatively quickly but back off giving more time to recover
-	// until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
-	const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout.
-	const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout.
-	const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules.
-
-	class LLEventPollResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(LLEventPollResponder);
-	public:
-		
-		static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender);
-		void stop();
-		
-		void makeRequest();
-
-		/* virtual */ void completedRaw(const LLChannelDescriptors& channels,
-								  const LLIOPipe::buffer_ptr_t& buffer);
-
-	private:
-		LLEventPollResponder(const std::string&	pollURL, const LLHost& sender);
-		~LLEventPollResponder();
-
-		
-		void handleMessage(const LLSD& content);
-
-		/* virtual */ void httpFailure();
-		/* virtual */ void httpSuccess();
-
-	private:
-
-		bool	mDone;
-
-		std::string			mPollURL;
-		std::string			mSender;
-		
-		LLSD	mAcknowledge;
-		
-		// these are only here for debugging so	we can see which poller	is which
-		static int sCount;
-		int	mCount;
-		S32 mErrorCount;
-	};
-
-	class LLEventPollEventTimer : public LLEventTimer
-	{
-		typedef LLPointer<LLEventPollResponder> EventPollResponderPtr;
-
-	public:
-		LLEventPollEventTimer(F32 period, EventPollResponderPtr responder)
-			: LLEventTimer(period), mResponder(responder)
-		{ }
-
-		virtual BOOL tick()
-		{
-			mResponder->makeRequest();
-			return TRUE;	// Causes this instance to be deleted.
-		}
-
-	private:
-		
-		EventPollResponderPtr mResponder;
-	};
-
-	//static
-	LLHTTPClient::ResponderPtr LLEventPollResponder::start(
-		const std::string& pollURL, const LLHost& sender)
-	{
-		LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender);
-		LL_INFOS()	<< "LLEventPollResponder::start <" << sCount << "> "
-				<< pollURL << LL_ENDL;
-		return result;
-	}
-
-	void LLEventPollResponder::stop()
-	{
-		LL_INFOS()	<< "LLEventPollResponder::stop	<" << mCount <<	"> "
-				<< mPollURL	<< LL_ENDL;
-		// there should	be a way to	stop a LLHTTPClient	request	in progress
-		mDone =	true;
-	}
-
-	int	LLEventPollResponder::sCount =	0;
-
-	LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender)
-		: mDone(false),
-		  mPollURL(pollURL),
-		  mCount(++sCount),
-		  mErrorCount(0)
-	{
-		//extract host and port of simulator to set as sender
-		LLViewerRegion *regionp = gAgent.getRegion();
-		if (!regionp)
-		{
-			LL_ERRS() << "LLEventPoll initialized before region is added." << LL_ENDL;
-		}
-		mSender = sender.getIPandPort();
-		LL_INFOS() << "LLEventPoll initialized with sender " << mSender << LL_ENDL;
-		makeRequest();
-	}
-
-	LLEventPollResponder::~LLEventPollResponder()
-	{
-		stop();
-		LL_DEBUGS() <<	"LLEventPollResponder::~Impl <" <<	mCount << "> "
-				 <<	mPollURL <<	LL_ENDL;
-	}
-
-	// virtual 
-	void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels,
-											const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		if (getStatus() == HTTP_BAD_GATEWAY)
-		{
-			// These errors are not parsable as LLSD, 
-			// which LLHTTPClient::Responder::completedRaw will try to do.
-			httpCompleted();
-		}
-		else
-		{
-			LLHTTPClient::Responder::completedRaw(channels,buffer);
-		}
-	}
-
-	void LLEventPollResponder::makeRequest()
-	{
-		LLSD request;
-		request["ack"] = mAcknowledge;
-		request["done"]	= mDone;
-		
-		LL_DEBUGS() <<	"LLEventPollResponder::makeRequest	<" << mCount <<	"> ack = "
-				 <<	LLSDXMLStreamer(mAcknowledge) << LL_ENDL;
-		LLHTTPClient::post(mPollURL, request, this);
-	}
-
-	void LLEventPollResponder::handleMessage(const	LLSD& content)
-	{
-		std::string	msg_name	= content["message"];
-		LLSD message;
-		message["sender"] = mSender;
-		message["body"] = content["body"];
-		LLMessageSystem::dispatch(msg_name, message);
-	}
-
-	//virtual
-	void LLEventPollResponder::httpFailure()
-	{
-		if (mDone) return;
-
-		// A HTTP_BAD_GATEWAY (502) error is our standard timeout response
-		// we get this when there are no events.
-		if ( getStatus() == HTTP_BAD_GATEWAY )
-		{
-			mErrorCount = 0;
-			makeRequest();
-		}
-		else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS)
-		{
-			++mErrorCount;
-			
-			// The 'tick' will return TRUE causing the timer to delete this.
-			new LLEventPollEventTimer(EVENT_POLL_ERROR_RETRY_SECONDS
-										+ mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC
-									, this);
-
-			LL_WARNS() << dumpResponse() << LL_ENDL;
-		}
-		else
-		{
-			LL_WARNS() << dumpResponse()
-					   << " [count:" << mCount << "] "
-					   << (mDone ? " -- done" : "") << LL_ENDL;
-			stop();
-
-			// At this point we have given up and the viewer will not receive HTTP messages from the simulator.
-			// IMs, teleports, about land, selecing land, region crossing and more will all fail.
-			// They are essentially disconnected from the region even though some things may still work.
-			// Since things won't get better until they relog we force a disconnect now.
-
-			// *NOTE:Mani - The following condition check to see if this failing event poll
-			// is attached to the Agent's main region. If so we disconnect the viewer.
-			// Else... its a child region and we just leave the dead event poll stopped and 
-			// continue running.
-			if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender)
-			{
-				LL_WARNS() << "Forcing disconnect due to stalled main region event poll."  << LL_ENDL;
-				LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
-			}
-		}
-	}
-
-	//virtual
-	void LLEventPollResponder::httpSuccess()
-	{
-		LL_DEBUGS() <<	"LLEventPollResponder::result <" << mCount	<< ">"
-				 <<	(mDone ? " -- done"	: "") << LL_ENDL;
-		
-		if (mDone) return;
-
-		mErrorCount = 0;
-
-		const LLSD& content = getContent();
-		if (!content.isMap() ||
-			!content.get("events") ||
-			!content.get("id"))
-		{
-			LL_WARNS() << "received event poll with no events or id key: " << dumpResponse() << LL_ENDL;
-			makeRequest();
-			return;
-		}
-		
-		mAcknowledge = content["id"];
-		LLSD events	= content["events"];
-
-		if(mAcknowledge.isUndefined())
-		{
-			LL_WARNS() << "LLEventPollResponder: id undefined" << LL_ENDL;
-		}
-		
-		// was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
-		LL_DEBUGS()  << "LLEventPollResponder::httpSuccess <" <<	mCount << "> " << events.size() << "events (id "
-					 <<	LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL;
-		
-		LLSD::array_const_iterator i = events.beginArray();
-		LLSD::array_const_iterator end = events.endArray();
-		for	(; i !=	end; ++i)
-		{
-			if (i->has("message"))
-			{
-				handleMessage(*i);
-			}
-		}
-		
-		makeRequest();
-	}	
+namespace Details
+{
+
+    class LLEventPollImpl
+    {
+    public:
+        LLEventPollImpl(const LLHost &sender);
+
+        void start(const std::string &url);
+        void stop();
+
+    private:
+        // We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
+        // This means we attempt to recover relatively quickly but back off giving more time to recover
+        // until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
+        static const F32                EVENT_POLL_ERROR_RETRY_SECONDS;
+        static const F32                EVENT_POLL_ERROR_RETRY_SECONDS_INC;
+        static const S32                MAX_EVENT_POLL_HTTP_ERRORS;
+
+        void                            eventPollCoro(std::string url);
+
+        void                            handleMessage(const LLSD &content);
+
+        bool                            mDone;
+        LLCore::HttpRequest::ptr_t      mHttpRequest;
+        LLCore::HttpRequest::policy_t   mHttpPolicy;
+        std::string                     mSenderIp;
+        int                             mCounter;
+        LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mAdapter;
+
+        static int                      sNextCounter;
+    };
+
+
+    const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout.
+    const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout.
+    const S32 LLEventPollImpl::MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules.
+
+    int LLEventPollImpl::sNextCounter = 1;
+
+
+    LLEventPollImpl::LLEventPollImpl(const LLHost &sender) :
+        mDone(false),
+        mHttpRequest(),
+        mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+        mSenderIp(),
+        mCounter(sNextCounter++)
+
+    {
+        LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+
+        mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
+        mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_LONG_POLL);
+        mSenderIp = sender.getIPandPort();
+    }
+
+    void LLEventPollImpl::handleMessage(const LLSD& content)
+    {
+        std::string	msg_name = content["message"];
+        LLSD message;
+        message["sender"] = mSenderIp;
+        message["body"] = content["body"];
+        LLMessageSystem::dispatch(msg_name, message);
+    }
+
+    void LLEventPollImpl::start(const std::string &url)
+    {
+        if (!url.empty())
+        {
+            std::string coroname =
+                LLCoros::instance().launch("LLEventPollImpl::eventPollCoro",
+                boost::bind(&LLEventPollImpl::eventPollCoro, this, url));
+            LL_INFOS("LLEventPollImpl") << coroname << " with  url '" << url << LL_ENDL;
+        }
+    }
+
+    void LLEventPollImpl::stop()
+    {
+        LL_INFOS() << "requesting stop for event poll coroutine <" << mCounter << ">" << LL_ENDL;
+        mDone = true;
+
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter = mAdapter.lock();
+        if (adapter)
+        {
+            // cancel the yielding operation if any.
+            adapter->cancelSuspendedOperation();
+        }
+    }
+
+    void LLEventPollImpl::eventPollCoro(std::string url)
+    {
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy));
+        LLSD acknowledge;
+        int errorCount = 0;
+        int counter = mCounter; // saved on the stack for logging. 
+
+        LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;
+
+        mAdapter = httpAdapter;
+
+        // continually poll for a server update until we've been flagged as 
+        // finished 
+        while (!mDone)
+        {
+            LLSD request;
+            request["ack"] = acknowledge;
+            request["done"] = mDone;
+
+//          LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = "
+//              << LLSDXMLStreamer(request) << LL_ENDL;
+
+            LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL;
+            LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request);
+
+//          LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "
+//              << LLSDXMLStreamer(result) << LL_ENDL;
+
+            LLSD httpResults = result["http_result"];
+            LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+            if (!status)
+            {
+                if (status == LLCore::HttpStatus(HTTP_BAD_GATEWAY))
+                {   // A HTTP_BAD_GATEWAY (502) error is our standard timeout response
+                    // we get this when there are no events.
+                    errorCount = 0;
+                    continue;
+                }
+                else if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) || 
+                        (status == LLCore::HttpStatus(HTTP_NOT_FOUND)))
+                {   // Event polling for this server has been canceled.  In 
+                    // some cases the server gets ahead of the viewer and will 
+                    // return a 404 error (Not Found) before the cancel event
+                    // comes back in the queue
+                    LL_WARNS() << "Canceling coroutine" << LL_ENDL;
+                    break;
+                }
+                LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
+                    << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;
+
+                if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS)
+                {   // An unanticipated error has been received from our poll 
+                    // request. Calculate a timeout and wait for it to expire(sleep)
+                    // before trying again.  The sleep time is increased by 5 seconds
+                    // for each consecutive error.
+                    LLEventTimeout timeout;
+                    ++errorCount;
+
+                    F32 waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS
+                        + errorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC;
+
+                    LL_WARNS("LLEventPollImpl") << "<" << counter << "> Retrying in " << waitToRetry <<
+                        " seconds, error count is now " << errorCount << LL_ENDL;
+
+                    timeout.eventAfter(waitToRetry, LLSD());
+                    llcoro::suspendUntilEventOn(timeout);
+                    
+                    if (mDone)
+                        break;
+                    LL_INFOS("LLEventPollImpl") << "<" << counter << "> About to retry request." << LL_ENDL;
+                    continue;
+                }
+                else
+                {
+                    // At this point we have given up and the viewer will not receive HTTP messages from the simulator.
+                    // IMs, teleports, about land, selecting land, region crossing and more will all fail.
+                    // They are essentially disconnected from the region even though some things may still work.
+                    // Since things won't get better until they relog we force a disconnect now.
+                    mDone = true;
+
+                    // *NOTE:Mani - The following condition check to see if this failing event poll
+                    // is attached to the Agent's main region. If so we disconnect the viewer.
+                    // Else... its a child region and we just leave the dead event poll stopped and 
+                    // continue running.
+                    if (gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSenderIp)
+                    {
+                        LL_WARNS("LLEventPollImpl") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL;
+                        LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
+                    }
+                    break;
+                }
+            }
+
+            errorCount = 0;
+
+            if (!result.isMap() ||
+                !result.get("events") ||
+                !result.get("id"))
+            {
+                LL_WARNS("LLEventPollImpl") << " <" << counter << "> received event poll with no events or id key: " << LLSDXMLStreamer(result) << LL_ENDL;
+                continue;
+            }
+
+            acknowledge = result["id"];
+            LLSD events = result["events"];
+
+            if (acknowledge.isUndefined())
+            {
+                LL_WARNS("LLEventPollImpl") << " id undefined" << LL_ENDL;
+            }
+
+            // was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
+            LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL;
+
+            LLSD::array_const_iterator i = events.beginArray();
+            LLSD::array_const_iterator end = events.endArray();
+            for (; i != end; ++i)
+            {
+                if (i->has("message"))
+                {
+                    handleMessage(*i);
+                }
+            }
+        }
+        LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL;
+    }
+
+}
 }
 
-LLEventPoll::LLEventPoll(const std::string&	poll_url, const LLHost& sender)
-	: mImpl(LLEventPollResponder::start(poll_url, sender))
-	{ }
+LLEventPoll::LLEventPoll(const std::string&	poll_url, const LLHost& sender):
+    mImpl()
+{ 
+    mImpl = boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl>
+            (new LLEventPolling::Details::LLEventPollImpl(sender));
+    mImpl->start(poll_url);
+}
 
 LLEventPoll::~LLEventPoll()
 {
-	LLHTTPClient::Responder* responderp = mImpl.get();
-	LLEventPollResponder* event_poll_responder = dynamic_cast<LLEventPollResponder*>(responderp);
-	if (event_poll_responder) event_poll_responder->stop();
+    mImpl->stop();
+
 }
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index e8d98062aaee1bce518e08c6b368e2a2a6983640..e2afd9226bcf9cbb0163bc1401b19a64992426b6 100755
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -27,10 +27,23 @@
 #ifndef LL_LLEVENTPOLL_H
 #define LL_LLEVENTPOLL_H
 
-#include "llhttpclient.h"
+#include "boost/move/unique_ptr.hpp"
+
+namespace boost
+{
+    using ::boost::movelib::unique_ptr; // move unique_ptr into the boost namespace.
+}
 
 class LLHost;
 
+namespace LLEventPolling
+{
+namespace Details
+{
+    class LLEventPollImpl;
+}
+}
+
 
 class LLEventPoll
 	///< implements the viewer side of server-to-viewer pushed events.
@@ -40,11 +53,11 @@ class LLEventPoll
 		///< Start polling the URL.
 
 	virtual ~LLEventPoll();
-		///< will stop polling, cancelling any poll in progress.
+		///< will stop polling, canceling any poll in progress.
 
 
 private:
-	LLHTTPClient::ResponderPtr mImpl;
+    boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl>    mImpl;
 };
 
 
diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp
deleted file mode 100644
index b50c81eedcf04e777993f8c73c80b23159abc967..0000000000000000000000000000000000000000
--- a/indra/newview/llexperienceassociationresponder.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/** 
- * @file llexperienceassociationresponder.cpp
- * @brief llexperienceassociationresponder implementation. This class combines 
- * a lookup for a script association and an experience details request. The first
- * is always async, but the second may be cached locally.
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llexperienceassociationresponder.h"
-#include "llexperiencecache.h"
-#include "llviewerregion.h"
-#include "llagent.h"
-
-ExperienceAssociationResponder::ExperienceAssociationResponder(ExperienceAssociationResponder::callback_t callback):mCallback(callback)
-{
-    ref();
-}
-
-void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& object_id, const LLUUID& item_id, callback_t callback )
-{
-    LLSD request;
-    request["object-id"]=object_id;
-    request["item-id"]=item_id;
-    fetchAssociatedExperience(request, callback);
-}
-
-void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback)
-{
-    LLViewerRegion* region = gAgent.getRegion();
-    if (region)
-    {
-        std::string lookup_url=region->getCapability("GetMetadata"); 
-        if(!lookup_url.empty())
-        {
-            LLSD fields;
-            fields.append("experience");
-            request["fields"] = fields;
-            LLHTTPClient::post(lookup_url, request, new ExperienceAssociationResponder(callback));
-        }
-    }
-}
-
-void ExperienceAssociationResponder::httpFailure()
-{
-    LLSD msg;
-    msg["error"]=(LLSD::Integer)getStatus();
-    msg["message"]=getReason();
-    LL_INFOS("ExperienceAssociation") << "Failed to look up associated experience: " << getStatus() << ": " << getReason() << LL_ENDL;
-
-    sendResult(msg);
-  
-}
-void ExperienceAssociationResponder::httpSuccess()
-{
-    if(!getContent().has("experience"))
-    {
-
-        LLSD msg;
-        msg["message"]="no experience";
-        msg["error"]=-1;
-        sendResult(msg);
-        return;
-    }
-
-    LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1));
-
-}
-
-void ExperienceAssociationResponder::sendResult( const LLSD& experience )
-{
-    mCallback(experience);
-    unref();
-}
-
-
-
diff --git a/indra/newview/llexperienceassociationresponder.h b/indra/newview/llexperienceassociationresponder.h
deleted file mode 100644
index 2bdc3d251b2c575e00f41067cc6df059959aacd7..0000000000000000000000000000000000000000
--- a/indra/newview/llexperienceassociationresponder.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "llhttpclient.h"
-#include "llsd.h"
-/** 
- * @file llexperienceassociationresponder.h
- * @brief llexperienceassociationresponder and related class definitions
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-
-
-#ifndef LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
-#define LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
-
-#include "llhttpclient.h"
-#include "llsd.h"
-
-class ExperienceAssociationResponder : public LLHTTPClient::Responder
-{
-public:
-    typedef boost::function<void(const LLSD& experience)> callback_t;
-
-    ExperienceAssociationResponder(callback_t callback);
-
-    /*virtual*/ void httpSuccess();
-    /*virtual*/ void httpFailure();
-
-    static void fetchAssociatedExperience(const LLUUID& object_it, const LLUUID& item_id, callback_t callback);
-
-private:    
-    static void fetchAssociatedExperience(LLSD& request, callback_t callback);
-    
-    void sendResult(const LLSD& experience);
-
-    callback_t mCallback;
-
-};
-
-#endif // LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 28319564e456863841255be346c1a780b220a4d3..1de4102dba6274b15aefd112d267b4b8c551eeb1 100755
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -34,7 +34,6 @@
 #include "llagent.h"
 #include "llcallingcard.h"			// for LLAvatarTracker
 #include "llcommandhandler.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llurlaction.h"
 #include "llimagepng.h"
@@ -42,9 +41,11 @@
 #include "lltrans.h"
 #include "llevents.h"
 #include "llviewerregion.h"
+#include "llviewercontrol.h"
 
 #include "llfloaterwebcontent.h"
 #include "llfloaterreg.h"
+#include "llcorehttputil.h"
 
 boost::scoped_ptr<LLEventPump> LLFacebookConnect::sStateWatcher(new LLEventStream("FacebookConnectState"));
 boost::scoped_ptr<LLEventPump> LLFacebookConnect::sInfoWatcher(new LLEventStream("FacebookConnectInfo"));
@@ -67,6 +68,24 @@ void toast_user_for_facebook_success()
     LLNotificationsUtil::add("FacebookConnect", args);
 }
 
+LLCore::HttpHeaders::ptr_t get_headers()
+{
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    // The DebugSlshareLogTag mechanism is intended to trigger slshare-service
+    // debug logging. slshare-service is coded to respond to an X-debug-tag
+    // header by engaging debug logging for that request only. This way a
+    // developer need not muck with the slshare-service image to engage debug
+    // logging. Moreover, the value of X-debug-tag is embedded in each such
+    // log line so the developer can quickly find the log lines pertinent to
+    // THIS session.
+    std::string logtag(gSavedSettings.getString("DebugSlshareLogTag"));
+    if (! logtag.empty())
+    {
+        httpHeaders->append("X-debug-tag", logtag);
+    }
+    return httpHeaders;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 //
 class LLFacebookConnectHandler : public LLCommandHandler
@@ -125,266 +144,349 @@ LLFacebookConnectHandler gFacebookConnectHandler;
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFacebookConnectResponder : public LLHTTPClient::Responder
+void LLFacebookConnect::facebookConnectCoro(std::string authCode, std::string authState)
 {
-	LOG_CLASS(LLFacebookConnectResponder);
-public:
-	
-    LLFacebookConnectResponder()
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    LLSD putData;
+    if (!authCode.empty())
     {
-        LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
+        putData["code"] = authCode;
+    }
+    if (!authState.empty())
+    {
+        putData["state"] = authState;
     }
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FacebookConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
-	}
 
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
-							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-				LLFacebookConnect::instance().openFacebookWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Connect", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->putAndSuspend(httpRequest, getFacebookConnectURL("/connection"), putData, httpOpts, get_headers());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    if (!status)
+    {
+        if (status == LLCore::HttpStatus(HTTP_FOUND))
+        {
+            std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+            if (location.empty())
+            {
+                LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
+            }
+            else
+            {
+                openFacebookWeb(location);
+            }
+        }
+    }
+    else
+    {
+        LL_INFOS("FacebookConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_CONNECTED);
+    }
+
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFacebookShareResponder : public LLHTTPClient::Responder
+bool LLFacebookConnect::testShareStatus(LLSD &result)
 {
-	LOG_CLASS(LLFacebookShareResponder);
-public:
-    
-	LLFacebookShareResponder()
-	{
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTING);
-	}
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-	/* virtual */ void httpSuccess()
-	{
-		toast_user_for_facebook_success();
-		LL_DEBUGS("FacebookConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
-	}
+    if (status)
+        return true;
 
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
-							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-				LLFacebookConnect::instance().openFacebookWeb(location);
-			}
-		}
-		else if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LLFacebookConnect::instance().connectToFacebook();
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POST_FAILED);
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Share", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openFacebookWeb(location);
+        }
+    }
+    if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+    {
+        LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL;
+        connectToFacebook();
+    }
+    else
+    {
+        LL_WARNS("FacebookConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_POST_FAILED);
+        log_facebook_connect_error("Share", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    return false;
+}
 
-///////////////////////////////////////////////////////////////////////////////
-//
-class LLFacebookDisconnectResponder : public LLHTTPClient::Responder
+void LLFacebookConnect::facebookShareCoro(std::string route, LLSD share)
 {
-	LOG_CLASS(LLFacebookDisconnectResponder);
-public:
- 
-	LLFacebookDisconnectResponder()
-	{
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	void setUserDisconnected()
-	{
-		// Clear data
-		LLFacebookConnect::instance().clearInfo();
-		LLFacebookConnect::instance().clearContent();
-		//Notify state change
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
-	}
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FacebookConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
-		setUserDisconnected();
-	}
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), share, httpOpts, get_headers());
 
-	/* virtual */ void httpFailure()
-	{
-		//User not found so already disconnected
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("FacebookConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
-			setUserDisconnected();
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Disconnect", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    if (testShareStatus(result))
+    {
+        toast_user_for_facebook_success();
+        LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_POSTED);
+    }
+}
+
+void LLFacebookConnect::facebookShareImageCoro(std::string route, LLPointer<LLImageFormatted> image, std::string caption)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(get_headers());
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    std::string imageFormat;
+    if (dynamic_cast<LLImagePNG*>(image.get()))
+    {
+        imageFormat = "png";
+    }
+    else if (dynamic_cast<LLImageJPEG*>(image.get()))
+    {
+        imageFormat = "jpg";
+    }
+    else
+    {
+        LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
+        return;
+    }
+
+    // All this code is mostly copied from LLWebProfile::post()
+    static const std::string boundary = "----------------------------0123abcdefab";
+
+    std::string contentType = "multipart/form-data; boundary=" + boundary;
+    httpHeaders->append("Content-Type", contentType.c_str());
+
+    LLCore::BufferArray::ptr_t raw = LLCore::BufferArray::ptr_t(new LLCore::BufferArray()); // 
+    LLCore::BufferArrayStream body(raw.get());
+
+    // *NOTE: The order seems to matter.
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"caption\"\r\n\r\n"
+        << caption << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
+        << "Content-Type: image/" << imageFormat << "\r\n\r\n";
+
+    // Insert the image data.
+    // *FIX: Treating this as a string will probably screw it up ...
+    U8* image_data = image->getData();
+    for (S32 i = 0; i < image->getDataSize(); ++i)
+    {
+        body << image_data[i];
+    }
+
+    body << "\r\n--" << boundary << "--\r\n";
+
+    setConnectionState(LLFacebookConnect::FB_POSTING);
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), raw, httpOpts, httpHeaders);
+
+    if (testShareStatus(result))
+    {
+        toast_user_for_facebook_success();
+        LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_POSTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFacebookConnectedResponder : public LLHTTPClient::Responder
+void LLFacebookConnect::facebookDisconnectCoro()
 {
-	LOG_CLASS(LLFacebookConnectedResponder);
-public:
-    
-	LLFacebookConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFacebookConnectURL("/connection"), httpOpts, get_headers());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    if (!status && (status != LLCore::HttpStatus(HTTP_FOUND)))
+    {
+        LL_WARNS("FacebookConnect") << "Failed to disconnect:" << status.toTerseString() << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
+        log_facebook_connect_error("Disconnect", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
     {
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
+        LL_DEBUGS("FacebookConnect") << "Facebook Disconnect successful. " << LL_ENDL;
+        clearInfo();
+        clearContent();
+        //Notify state change
+        setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
     }
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FacebookConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-		LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTED);
-	}
+}
 
-	/* virtual */ void httpFailure()
-	{
-		// show the facebook login page if not connected yet
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("FacebookConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
-			if (mAutoConnect)
-			{
-				LLFacebookConnect::instance().connectToFacebook();
-			}
-			else
-			{
-				LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
-			}
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Connected", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-    
-private:
-	bool mAutoConnect;
-};
+///////////////////////////////////////////////////////////////////////////////
+//
+void LLFacebookConnect::facebookConnectedCheckCoro(bool autoConnect)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
+
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/connection", true), httpOpts, get_headers());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        if ( status == LLCore::HttpStatus(HTTP_NOT_FOUND) )
+        {
+            LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL;
+            if (autoConnect)
+            {
+                connectToFacebook();
+            }
+            else
+            {
+                setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
+            }
+        }
+        else
+        {
+            LL_WARNS("FacebookConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
+
+            setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
+            log_facebook_connect_error("Connected", status.getStatus(), status.toString(),
+                result.get("error_code"), result.get("error_description"));
+        }
+    }
+    else
+    {
+        LL_DEBUGS("FacebookConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLFacebookConnect::FB_CONNECTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFacebookInfoResponder : public LLHTTPClient::Responder
+void LLFacebookConnect::facebookConnectInfoCoro()
 {
-	LOG_CLASS(LLFacebookInfoResponder);
-public:
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_INFOS("FacebookConnect") << "Facebook: Info received" << LL_ENDL;
-		LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. " << dumpResponse() << LL_ENDL;
-		LLFacebookConnect::instance().storeInfo(getContent());
-	}
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
 
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-				LLFacebookConnect::instance().openFacebookWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Info", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/info", true), httpOpts, get_headers());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openFacebookWeb(location);
+        }
+    }
+    else if (!status)
+    {
+        LL_WARNS("FacebookConnect") << "Facebook Info failed: " << status.toString() << LL_ENDL;
+        log_facebook_connect_error("Info", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_INFOS("FacebookConnect") << "Facebook: Info received" << LL_ENDL;
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        storeInfo(result);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFacebookFriendsResponder : public LLHTTPClient::Responder
+void LLFacebookConnect::facebookConnectFriendsCoro()
 {
-	LOG_CLASS(LLFacebookFriendsResponder);
-public:
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FacebookConnect") << "Getting Facebook friends successful. " << dumpResponse() << LL_ENDL;
-		LLFacebookConnect::instance().storeContent(getContent());
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
-							 << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-				LLFacebookConnect::instance().openFacebookWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("FacebookConnect") << dumpResponse() << LL_ENDL;
-			const LLSD& content = getContent();
-			log_facebook_connect_error("Friends", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/friends", true), httpOpts, get_headers());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openFacebookWeb(location);
+        }
+    }
+    else if (!status)
+    {
+        LL_WARNS("FacebookConnect") << "Facebook Friends failed: " << status.toString() << LL_ENDL;
+        log_facebook_connect_error("Info", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_INFOS("FacebookConnect") << "Facebook: Friends received" << LL_ENDL;
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        LLSD content = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
+        storeContent(content);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
@@ -439,40 +541,32 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
 
 void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
 {
-	LLSD body;
-	if (!auth_code.empty())
-    {
-		body["code"] = auth_code;
-    }
-	if (!auth_state.empty())
-    {
-		body["state"] = auth_state;
-    }
-    
-	LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder());
+    setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
+
+    LLCoros::instance().launch("LLFacebookConnect::facebookConnectCoro",
+        boost::bind(&LLFacebookConnect::facebookConnectCoro, this, auth_code, auth_state));
 }
 
 void LLFacebookConnect::disconnectFromFacebook()
 {
-	LLHTTPClient::del(getFacebookConnectURL("/connection"), new LLFacebookDisconnectResponder());
+    LLCoros::instance().launch("LLFacebookConnect::facebookDisconnectCoro",
+        boost::bind(&LLFacebookConnect::facebookDisconnectCoro, this));
 }
 
 void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
 {
-	const bool follow_redirects = false;
-	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect),
-						LLSD(), timeout, follow_redirects);
+    setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
+
+    LLCoros::instance().launch("LLFacebookConnect::facebookConnectedCheckCoro",
+        boost::bind(&LLFacebookConnect::facebookConnectedCheckCoro, this, auto_connect));
 }
 
 void LLFacebookConnect::loadFacebookInfo()
 {
 	if(mRefreshInfo)
 	{
-		const bool follow_redirects = false;
-		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		LLHTTPClient::get(getFacebookConnectURL("/info", true), new LLFacebookInfoResponder(),
-			LLSD(), timeout, follow_redirects);
+        LLCoros::instance().launch("LLFacebookConnect::facebookConnectInfoCoro",
+            boost::bind(&LLFacebookConnect::facebookConnectInfoCoro, this));
 	}
 }
 
@@ -480,15 +574,16 @@ void LLFacebookConnect::loadFacebookFriends()
 {
 	if(mRefreshContent)
 	{
-		const bool follow_redirects = false;
-		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		LLHTTPClient::get(getFacebookConnectURL("/friends", true), new LLFacebookFriendsResponder(),
-			LLSD(), timeout, follow_redirects);
+        LLCoros::instance().launch("LLFacebookConnect::facebookConnectFriendsCoro",
+            boost::bind(&LLFacebookConnect::facebookConnectFriendsCoro, this));
 	}
 }
 
-void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& image, const std::string& message)
+void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, 
+    const std::string& description, const std::string& image, const std::string& message)
 {
+    setConnectionState(LLFacebookConnect::FB_POSTING);
+
 	LLSD body;
 	if (!location.empty())
     {
@@ -511,80 +606,39 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri
 		body["message"] = message;
     }
 
-	// Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder());
+    LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
+        boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/checkin", body));
 }
 
 void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption)
 {
+    setConnectionState(LLFacebookConnect::FB_POSTING);
+
 	LLSD body;
 	body["image"] = image_url;
 	body["caption"] = caption;
 	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getFacebookConnectURL("/share/photo", true), body, new LLFacebookShareResponder());
+    LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
+        boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/photo", body));
 }
 
 void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption)
 {
-	std::string imageFormat;
-	if (dynamic_cast<LLImagePNG*>(image.get()))
-	{
-		imageFormat = "png";
-	}
-	else if (dynamic_cast<LLImageJPEG*>(image.get()))
-	{
-		imageFormat = "jpg";
-	}
-	else
-	{
-		LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
-		return;
-	}
-	
-	// All this code is mostly copied from LLWebProfile::post()
-	const std::string boundary = "----------------------------0123abcdefab";
-
-	LLSD headers;
-	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
-
-	std::ostringstream body;
-
-	// *NOTE: The order seems to matter.
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"caption\"\r\n\r\n"
-			<< caption << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
-			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
-
-	// Insert the image data.
-	// *FIX: Treating this as a string will probably screw it up ...
-	U8* image_data = image->getData();
-	for (S32 i = 0; i < image->getDataSize(); ++i)
-	{
-		body << image_data[i];
-	}
+    setConnectionState(LLFacebookConnect::FB_POSTING);
 
-	body <<	"\r\n--" << boundary << "--\r\n";
-
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = body.str().size();
-	U8 *data = new U8[size];
-	memcpy(data, body.str().data(), size);
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::postRaw(getFacebookConnectURL("/share/photo", true), data, size, new LLFacebookShareResponder(), headers);
+    LLCoros::instance().launch("LLFacebookConnect::facebookShareImageCoro",
+        boost::bind(&LLFacebookConnect::facebookShareImageCoro, this, "/share/photo", image, caption));
 }
 
 void LLFacebookConnect::updateStatus(const std::string& message)
 {
 	LLSD body;
 	body["message"] = message;
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getFacebookConnectURL("/share/wall", true), body, new LLFacebookShareResponder());
+
+    setConnectionState(LLFacebookConnect::FB_POSTING);
+
+    LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
+        boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/wall", body));
 }
 
 void LLFacebookConnect::storeInfo(const LLSD& info)
diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h
index c157db21781b7ff101297656f62dd5e4b0e128c2..2a2cdb54991d432344412720500b5f2a9bb1b353 100644
--- a/indra/newview/llfacebookconnect.h
+++ b/indra/newview/llfacebookconnect.h
@@ -30,6 +30,8 @@
 
 #include "llsingleton.h"
 #include "llimage.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLEventPump;
 
@@ -101,6 +103,15 @@ class LLFacebookConnect : public LLSingleton<LLFacebookConnect>
 	static boost::scoped_ptr<LLEventPump> sStateWatcher;
 	static boost::scoped_ptr<LLEventPump> sInfoWatcher;
 	static boost::scoped_ptr<LLEventPump> sContentWatcher;
+
+    bool testShareStatus(LLSD &results);
+    void facebookConnectCoro(std::string authCode, std::string authState);
+    void facebookConnectedCheckCoro(bool autoConnect);
+    void facebookDisconnectCoro();
+    void facebookShareCoro(std::string route, LLSD share);
+    void facebookShareImageCoro(std::string route, LLPointer<LLImageFormatted> image, std::string caption);
+    void facebookConnectInfoCoro();
+    void facebookConnectFriendsCoro();
 };
 
 #endif // LL_LLFACEBOOKCONNECT_H
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index ea39f812fd14cffa71991b0ae53b123227a6f0bf..f08064d9b51b1fbd052a992e2c1c9221ff388e8e 100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -40,7 +40,6 @@
 
 #include "llappviewer.h"
 #include "llbufferstream.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llviewercontrol.h"
 #include "llworld.h"
@@ -55,6 +54,7 @@
 #include "llviewershadermgr.h"
 #include "llstring.h"
 #include "stringize.h"
+#include "llcorehttputil.h"
 
 #if LL_WINDOWS
 #include "lldxhardware.h"
@@ -492,95 +492,70 @@ bool LLFeatureManager::loadGPUClass()
 	return true; // indicates that a gpu value was established
 }
 
-	
-// responder saves table into file
-class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder
+void LLFeatureManager::fetchFeatureTableCoro(std::string tableName)
 {
-	LOG_CLASS(LLHTTPFeatureTableResponder);
-public:
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FeatureManagerHTTPTable", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-	LLHTTPFeatureTableResponder(std::string filename) :
-		mFilename(filename)
-	{
-	}
+    const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable");
 
-	
-	virtual void completedRaw(const LLChannelDescriptors& channels,
-							  const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		if (isGoodStatus())
-		{
-			// write to file
-
-			LL_INFOS() << "writing feature table to " << mFilename << LL_ENDL;
-			
-			S32 file_size = buffer->countAfter(channels.in(), NULL);
-			if (file_size > 0)
-			{
-				// read from buffer
-				U8* copy_buffer = new U8[file_size];
-				buffer->readAfter(channels.in(), NULL, copy_buffer, file_size);
-
-				// write to file
-				LLAPRFile out(mFilename, LL_APR_WB);
-				out.write(copy_buffer, file_size);
-				out.close();
-			}
-		}
-		else
-		{
-			char body[1025]; 
-			body[1024] = '\0';
-			LLBufferStream istr(channels, buffer.get());
-			istr.get(body,1024);
-			if (strlen(body) > 0)
-			{
-				mContent["body"] = body;
-			}
-			LL_WARNS() << dumpResponse() << LL_ENDL;
-		}
-	}
-	
-private:
-	std::string mFilename;
-};
-
-void fetch_feature_table(std::string table)
-{
-	const std::string base       = gSavedSettings.getString("FeatureManagerHTTPTable");
 
 #if LL_WINDOWS
-	std::string os_string = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
-	std::string filename;
-	if (os_string.find("Microsoft Windows XP") == 0)
-	{
-		filename = llformat(table.c_str(), "_xp", LLVersionInfo::getVersion().c_str());
-	}
-	else
-	{
-		filename = llformat(table.c_str(), "", LLVersionInfo::getVersion().c_str());
-	}
+    std::string os_string = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
+    std::string filename;
+
+    if (os_string.find("Microsoft Windows XP") == 0)
+    {
+        filename = llformat(tableName.c_str(), "_xp", LLVersionInfo::getVersion().c_str());
+    }
+    else
+    {
+        filename = llformat(tableName.c_str(), "", LLVersionInfo::getVersion().c_str());
+    }
 #else
-	const std::string filename   = llformat(table.c_str(), LLVersionInfo::getVersion().c_str());
+    const std::string filename   = llformat(tableName.c_str(), LLVersionInfo::getVersion().c_str());
 #endif
 
-	const std::string url        = base + "/" + filename;
+    std::string url        = base + "/" + filename;
+    // testing url below
+    //url = "http://viewer-settings.secondlife.com/featuretable.2.1.1.208406.txt";
+    const std::string path       = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename);
 
-	const std::string path       = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename);
 
-	LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL;
-	
-	LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path));
-}
+    LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL;
+
+    LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status)
+    {   // There was a newer feature table on the server. We've grabbed it and now should write it.
+        // write to file
+        const LLSD::Binary &raw = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
 
+        LL_INFOS() << "writing feature table to " << path << LL_ENDL;
+
+        S32 size = raw.size();
+        if (size > 0)
+        {
+            // write to file
+            LLAPRFile out(path, LL_APR_WB);
+            out.write(raw.data(), size);
+            out.close();
+        }
+    }
+}
 
 // fetch table(s) from a website (S3)
 void LLFeatureManager::fetchHTTPTables()
 {
-	fetch_feature_table(FEATURE_TABLE_VER_FILENAME);
+    LLCoros::instance().launch("LLFeatureManager::fetchFeatureTableCoro",
+        boost::bind(&LLFeatureManager::fetchFeatureTableCoro, this, FEATURE_TABLE_VER_FILENAME));
 }
 
-
 void LLFeatureManager::cleanupFeatureTables()
 {
 	std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer());
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 69078ccc21504848965fa42aba6514fc506dd140..12ea691b491f0363ab19d6f62b98c1b69e253481 100755
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -32,6 +32,8 @@
 #include "llsingleton.h"
 #include "llstring.h"
 #include <map>
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 typedef enum EGPUClass
 {
@@ -164,6 +166,7 @@ class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManag
 
 	void initBaseMask();
 
+    void fetchFeatureTableCoro(std::string name);
 
 	std::map<std::string, LLFeatureList *> mMaskList;
 	std::set<std::string> mSkippedFeatures;
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index ef50594febf478f79d05d463f5a97a963a7f2159..a7236d1778f42b1a58d45bd9291a2b3c44784934 100755
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -40,6 +40,10 @@
 #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
 #endif // LL_SDL
 
+#if LL_LINUX || LL_SOLARIS
+#include "llhttpconstants.h"    // file picker uses some of thes constants on Linux
+#endif
+
 //
 // Globals
 //
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index b75660ea003a2635699c2fb081a14f987df4e9e4..c0ca5b8cf83c2c98a30cda9a2f103c4f1b597fab 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -32,7 +32,6 @@
 #include "llagent.h"
 #include "llcallingcard.h"			// for LLAvatarTracker
 #include "llcommandhandler.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llurlaction.h"
 #include "llimagepng.h"
@@ -43,6 +42,7 @@
 
 #include "llfloaterwebcontent.h"
 #include "llfloaterreg.h"
+#include "llcorehttputil.h"
 
 boost::scoped_ptr<LLEventPump> LLFlickrConnect::sStateWatcher(new LLEventStream("FlickrConnectState"));
 boost::scoped_ptr<LLEventPump> LLFlickrConnect::sInfoWatcher(new LLEventStream("FlickrConnectInfo"));
@@ -67,228 +67,322 @@ void toast_user_for_flickr_success()
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFlickrConnectResponder : public LLHTTPClient::Responder
+void LLFlickrConnect::flickrConnectCoro(std::string requestToken, std::string oauthVerifier)
 {
-	LOG_CLASS(LLFlickrConnectResponder);
-public:
-	
-    LLFlickrConnectResponder()
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD body;
+    if (!requestToken.empty())
+        body["request_token"] = requestToken;
+    if (!oauthVerifier.empty())
+        body["oauth_verifier"] = oauthVerifier;
+
+    setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+
+    LLSD result = httpAdapter->putAndSuspend(httpRequest, getFlickrConnectURL("/connection"), body, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        if ( status == LLCore::HttpStatus(HTTP_FOUND) )
+        {
+            std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+            if (location.empty())
+            {
+                LL_WARNS("FlickrConnect") << "Missing Location header " << LL_ENDL;
+            }
+            else
+            {
+                openFlickrWeb(location);
+            }
+        }
+        else
+        {
+            LL_WARNS("FlickrConnect") << "Connection failed " << status.toString() << LL_ENDL;
+            setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+            log_flickr_connect_error("Connect", status.getStatus(), status.toString(),
+                result.get("error_code"), result.get("error_description"));
+        }
+    }
+    else
     {
-        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+        LL_DEBUGS("FlickrConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
     }
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLFlickrConnect::instance().openFlickrWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
-            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
-			const LLSD& content = getContent();
-			log_flickr_connect_error("Connect", getStatus(), getReason(),
-                                      content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFlickrShareResponder : public LLHTTPClient::Responder
+bool LLFlickrConnect::testShareStatus(LLSD &result)
 {
-	LOG_CLASS(LLFlickrShareResponder);
-public:
-    
-	LLFlickrShareResponder()
-	{
-		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTING);
-	}
-	
-	/* virtual */ void httpSuccess()
-	{
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status)
+        return true;
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("FlickrConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openFlickrWeb(location);
+        }
+    }
+    if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+    {
+        LL_DEBUGS("FlickrConnect") << "Not connected. " << LL_ENDL;
+        connectToFlickr();
+    }
+    else
+    {
+        LL_WARNS("FlickrConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
+        log_flickr_connect_error("Share", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    return false;
+}
+
+void LLFlickrConnect::flickrShareCoro(LLSD share)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getFlickrConnectURL("/share/photo", true), share, httpOpts);
+
+    if (testShareStatus(result))
+    {
         toast_user_for_flickr_success();
-		LL_DEBUGS("FlickrConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
-        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLFlickrConnect::instance().openFlickrWeb(location);
-			}
-		}
-		else if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LLFlickrConnect::instance().connectToFlickr();
-		}
-		else
-		{
-			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
-            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
-			const LLSD& content = getContent();
-			log_flickr_connect_error("Share", getStatus(), getReason(),
-                                      content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+        LL_DEBUGS("FlickrConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_POSTED);
+    }
+
+}
+
+void LLFlickrConnect::flickrShareImageCoro(LLPointer<LLImageFormatted> image, std::string title, std::string description, std::string tags, int safetyLevel)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    std::string imageFormat;
+    if (dynamic_cast<LLImagePNG*>(image.get()))
+    {
+        imageFormat = "png";
+    }
+    else if (dynamic_cast<LLImageJPEG*>(image.get()))
+    {
+        imageFormat = "jpg";
+    }
+    else
+    {
+        LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
+        return;
+    }
+
+    // All this code is mostly copied from LLWebProfile::post()
+    const std::string boundary = "----------------------------0123abcdefab";
+
+    std::string contentType = "multipart/form-data; boundary=" + boundary;
+    httpHeaders->append("Content-Type", contentType.c_str());
+
+    LLCore::BufferArray::ptr_t raw = LLCore::BufferArray::ptr_t(new LLCore::BufferArray()); // 
+    LLCore::BufferArrayStream body(raw.get());
+
+    // *NOTE: The order seems to matter.
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"title\"\r\n\r\n"
+        << title << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
+        << description << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"tags\"\r\n\r\n"
+        << tags << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n"
+        << safetyLevel << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
+        << "Content-Type: image/" << imageFormat << "\r\n\r\n";
+
+    // Insert the image data.
+    // *FIX: Treating this as a string will probably screw it up ...
+    U8* image_data = image->getData();
+    for (S32 i = 0; i < image->getDataSize(); ++i)
+    {
+        body << image_data[i];
+    }
+
+    body << "\r\n--" << boundary << "--\r\n";
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getFlickrConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
+
+    if (testShareStatus(result))
+    {
+        toast_user_for_flickr_success();
+        LL_DEBUGS("FlickrConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_POSTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFlickrDisconnectResponder : public LLHTTPClient::Responder
+void LLFlickrConnect::flickrDisconnectCoro()
 {
-	LOG_CLASS(LLFlickrDisconnectResponder);
-public:
- 
-	LLFlickrDisconnectResponder()
-	{
-		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	void setUserDisconnected()
-	{
-		// Clear data
-		LLFlickrConnect::instance().clearInfo();
+    setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
+    httpOpts->setFollowRedirects(false);
 
-		//Notify state change
-		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
-	}
+    LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFlickrConnectURL("/connection"), httpOpts);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FlickrConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
-		setUserDisconnected();
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		//User not found so already disconnected
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("FlickrConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
-			setUserDisconnected();
-		}
-		else
-		{
-			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
-			LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
-			const LLSD& content = getContent();
-			log_flickr_connect_error("Disconnect", getStatus(), getReason(),
-                                      content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status && (status != LLCore::HttpStatus(HTTP_NOT_FOUND)))
+    {
+        LL_WARNS("FlickrConnect") << "Disconnect failed!" << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
+
+        log_flickr_connect_error("Disconnect", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_DEBUGS("FlickrConnect") << "Disconnect successful. " << LL_ENDL;
+        clearInfo();
+        setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFlickrConnectedResponder : public LLHTTPClient::Responder
+void LLFlickrConnect::flickrConnectedCoro(bool autoConnect)
 {
-	LOG_CLASS(LLFlickrConnectedResponder);
-public:
-    
-	LLFlickrConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getFlickrConnectURL("/connection", true), httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
     {
-		LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
+        if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+        {
+            LL_DEBUGS("FlickrConnect") << "Not connected. " << LL_ENDL;
+            if (autoConnect)
+            {
+                connectToFlickr();
+            }
+            else
+            {
+                setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
+            }
+        }
+        else
+        {
+            LL_WARNS("FlickrConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
+
+            setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
+            log_flickr_connect_error("Connected", status.getStatus(), status.toString(),
+                result.get("error_code"), result.get("error_description"));
+        }
+    }
+    else
+    {
+        LL_DEBUGS("FlickrConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
     }
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-        LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		// show the facebook login page if not connected yet
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("FlickrConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
-			if (mAutoConnect)
-			{
-                LLFlickrConnect::instance().connectToFlickr();
-			}
-			else
-			{
-                LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
-			}
-		}
-		else
-		{
-			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
-            LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
-			const LLSD& content = getContent();
-			log_flickr_connect_error("Connected", getStatus(), getReason(),
-                                      content.get("error_code"), content.get("error_description"));
-		}
-	}
-    
-private:
-	bool mAutoConnect;
-};
+
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLFlickrInfoResponder : public LLHTTPClient::Responder
+void LLFlickrConnect::flickrInfoCoro()
 {
-	LOG_CLASS(LLFlickrInfoResponder);
-public:
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_INFOS("FlickrConnect") << "Flickr: Info received" << LL_ENDL;
-		LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. " << dumpResponse() << LL_ENDL;
-        LLFlickrConnect::instance().storeInfo(getContent());
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLFlickrConnect::instance().openFlickrWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
-			const LLSD& content = getContent();
-			log_flickr_connect_error("Info", getStatus(), getReason(),
-                                      content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getFlickrConnectURL("/info", true), httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("FlickrConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openFlickrWeb(location);
+        }
+    }
+    else if (!status)
+    {
+        LL_WARNS("FlickrConnect") << "Flickr Info failed: " << status.toString() << LL_ENDL;
+        log_flickr_connect_error("Info", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_INFOS("FlickrConnect") << "Flickr: Info received" << LL_ENDL;
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        storeInfo(result);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
@@ -341,36 +435,28 @@ std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool
 
 void LLFlickrConnect::connectToFlickr(const std::string& request_token, const std::string& oauth_verifier)
 {
-	LLSD body;
-	if (!request_token.empty())
-		body["request_token"] = request_token;
-	if (!oauth_verifier.empty())
-		body["oauth_verifier"] = oauth_verifier;
-    
-	LLHTTPClient::put(getFlickrConnectURL("/connection"), body, new LLFlickrConnectResponder());
+    LLCoros::instance().launch("LLFlickrConnect::flickrConnectCoro",
+        boost::bind(&LLFlickrConnect::flickrConnectCoro, this, request_token, oauth_verifier));
 }
 
 void LLFlickrConnect::disconnectFromFlickr()
 {
-	LLHTTPClient::del(getFlickrConnectURL("/connection"), new LLFlickrDisconnectResponder());
+    LLCoros::instance().launch("LLFlickrConnect::flickrDisconnectCoro",
+        boost::bind(&LLFlickrConnect::flickrDisconnectCoro, this));
 }
 
 void LLFlickrConnect::checkConnectionToFlickr(bool auto_connect)
 {
-	const bool follow_redirects = false;
-	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	LLHTTPClient::get(getFlickrConnectURL("/connection", true), new LLFlickrConnectedResponder(auto_connect),
-						LLSD(), timeout, follow_redirects);
+    LLCoros::instance().launch("LLFlickrConnect::flickrConnectedCoro",
+        boost::bind(&LLFlickrConnect::flickrConnectedCoro, this, auto_connect));
 }
 
 void LLFlickrConnect::loadFlickrInfo()
 {
 	if(mRefreshInfo)
 	{
-		const bool follow_redirects = false;
-		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		LLHTTPClient::get(getFlickrConnectURL("/info", true), new LLFlickrInfoResponder(),
-			LLSD(), timeout, follow_redirects);
+        LLCoros::instance().launch("LLFlickrConnect::flickrInfoCoro",
+            boost::bind(&LLFlickrConnect::flickrInfoCoro, this));
 	}
 }
 
@@ -382,74 +468,20 @@ void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::strin
 	body["description"] = description;
 	body["tags"] = tags;
 	body["safety_level"] = safety_level;
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getFlickrConnectURL("/share/photo", true), body, new LLFlickrShareResponder());
+
+    setConnectionState(LLFlickrConnect::FLICKR_POSTING);
+
+    LLCoros::instance().launch("LLFlickrConnect::flickrShareCoro",
+        boost::bind(&LLFlickrConnect::flickrShareCoro, this, body));
 }
 
 void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
 {
-	std::string imageFormat;
-	if (dynamic_cast<LLImagePNG*>(image.get()))
-	{
-		imageFormat = "png";
-	}
-	else if (dynamic_cast<LLImageJPEG*>(image.get()))
-	{
-		imageFormat = "jpg";
-	}
-	else
-	{
-		LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
-		return;
-	}
-	
-	// All this code is mostly copied from LLWebProfile::post()
-	const std::string boundary = "----------------------------0123abcdefab";
-
-	LLSD headers;
-	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
-
-	std::ostringstream body;
-
-	// *NOTE: The order seems to matter.
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"title\"\r\n\r\n"
-			<< title << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
-			<< description << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"tags\"\r\n\r\n"
-			<< tags << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n"
-			<< safety_level << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
-			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
-
-	// Insert the image data.
-	// *FIX: Treating this as a string will probably screw it up ...
-	U8* image_data = image->getData();
-	for (S32 i = 0; i < image->getDataSize(); ++i)
-	{
-		body << image_data[i];
-	}
-
-	body <<	"\r\n--" << boundary << "--\r\n";
+    setConnectionState(LLFlickrConnect::FLICKR_POSTING);
 
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = body.str().size();
-	U8 *data = new U8[size];
-	memcpy(data, body.str().data(), size);
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::postRaw(getFlickrConnectURL("/share/photo", true), data, size, new LLFlickrShareResponder(), headers);
+    LLCoros::instance().launch("LLFlickrConnect::flickrShareImageCoro",
+        boost::bind(&LLFlickrConnect::flickrShareImageCoro, this, image, 
+        title, description, tags, safety_level));
 }
 
 void LLFlickrConnect::storeInfo(const LLSD& info)
diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h
index b127e6e10405deb936e49b310b555fe1bd29d5da..0155804da0f95e766822374b5e416435de6a9728 100644
--- a/indra/newview/llflickrconnect.h
+++ b/indra/newview/llflickrconnect.h
@@ -30,6 +30,8 @@
 
 #include "llsingleton.h"
 #include "llimage.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLEventPump;
 
@@ -93,6 +95,15 @@ class LLFlickrConnect : public LLSingleton<LLFlickrConnect>
 	static boost::scoped_ptr<LLEventPump> sStateWatcher;
 	static boost::scoped_ptr<LLEventPump> sInfoWatcher;
 	static boost::scoped_ptr<LLEventPump> sContentWatcher;
+
+    bool testShareStatus(LLSD &result);
+    void flickrConnectCoro(std::string requestToken, std::string oauthVerifier);
+    void flickrShareCoro(LLSD share);
+    void flickrShareImageCoro(LLPointer<LLImageFormatted> image, std::string title, std::string description, std::string tags, int safetyLevel);
+    void flickrDisconnectCoro();
+    void flickrConnectedCoro(bool autoConnect);
+    void flickrInfoCoro();
+
 };
 
 #endif // LL_LLFLICKRCONNECT_H
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index e71daa606780c2640a6d4a27e4c7f674bf861599..7bd01f6beb9aead6c8b02fe17d65d5732ab3ffda 100755
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -48,7 +48,6 @@
 // Linden library includes
 #include "llaudioengine.h"
 #include "llbutton.h"
-#include "llcurl.h"
 #include "llglheaders.h"
 #include "llfloater.h"
 #include "llfloaterreg.h"
@@ -61,6 +60,7 @@
 #include "stringize.h"
 #include "llsdutil_math.h"
 #include "lleventapi.h"
+#include "llcorehttputil.h"
 
 #if LL_WINDOWS
 #include "lldxhardware.h"
@@ -69,18 +69,6 @@
 extern LLMemoryInfo gSysMemory;
 extern U32 gPacketsIn;
 
-///----------------------------------------------------------------------------
-/// Class LLServerReleaseNotesURLFetcher
-///----------------------------------------------------------------------------
-class LLServerReleaseNotesURLFetcher : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLServerReleaseNotesURLFetcher);
-public:
-	static void startFetch();
-private:
-	/* virtual */ void httpCompleted();
-};
-
 ///----------------------------------------------------------------------------
 /// Class LLFloaterAbout
 ///----------------------------------------------------------------------------
@@ -102,6 +90,9 @@ class LLFloaterAbout
 
 private:
 	void setSupportText(const std::string& server_release_notes_url);
+
+    static void startFetchServerReleaseNotes();
+    static void handleServerReleaseNotes(LLSD results);
 };
 
 
@@ -138,7 +129,7 @@ BOOL LLFloaterAbout::postBuild()
 	{
 		// start fetching server release notes URL
 		setSupportText(LLTrans::getString("RetrievingData"));
-		LLServerReleaseNotesURLFetcher::startFetch();
+        startFetchServerReleaseNotes();
 	}
 	else // not logged in
 	{
@@ -201,6 +192,50 @@ LLSD LLFloaterAbout::getInfo()
 	return LLAppViewer::instance()->getViewerInfo();
 }
 
+/*static*/
+void LLFloaterAbout::startFetchServerReleaseNotes()
+{
+    LLViewerRegion* region = gAgent.getRegion();
+    if (!region) return;
+
+    // We cannot display the URL returned by the ServerReleaseNotes capability
+    // because opening it in an external browser will trigger a warning about untrusted
+    // SSL certificate.
+    // So we query the URL ourselves, expecting to find
+    // an URL suitable for external browsers in the "Location:" HTTP header.
+    std::string cap_url = region->getCapability("ServerReleaseNotes");
+
+    LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url,
+        &LLFloaterAbout::handleServerReleaseNotes, &LLFloaterAbout::handleServerReleaseNotes);
+
+}
+
+/*static*/
+void LLFloaterAbout::handleServerReleaseNotes(LLSD results)
+{
+//     LLFloaterAbout* floater_about = LLFloaterReg::getTypedInstance<LLFloaterAbout>("sl_about");
+//     if (floater_about)
+//     {
+        LLSD http_headers;
+        if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
+        {
+            LLSD http_results = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+            http_headers = http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+        }
+        else
+        {
+            http_headers = results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+        }
+        
+        std::string location = http_headers[HTTP_IN_HEADER_LOCATION].asString();
+        if (location.empty())
+        {
+            location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
+        }
+        LLAppViewer::instance()->setServerReleaseNotesURL(location);
+//    }
+}
+
 class LLFloaterAboutListener: public LLEventAPI
 {
 public:
@@ -265,35 +300,3 @@ void LLFloaterAboutUtil::registerFloater()
 
 }
 
-///----------------------------------------------------------------------------
-/// Class LLServerReleaseNotesURLFetcher implementation
-///----------------------------------------------------------------------------
-// static
-void LLServerReleaseNotesURLFetcher::startFetch()
-{
-	LLViewerRegion* region = gAgent.getRegion();
-	if (!region) return;
-
-	// We cannot display the URL returned by the ServerReleaseNotes capability
-	// because opening it in an external browser will trigger a warning about untrusted
-	// SSL certificate.
-	// So we query the URL ourselves, expecting to find
-	// an URL suitable for external browsers in the "Location:" HTTP header.
-	std::string cap_url = region->getCapability("ServerReleaseNotes");
-	LLHTTPClient::get(cap_url, new LLServerReleaseNotesURLFetcher);
-}
-
-// virtual
-void LLServerReleaseNotesURLFetcher::httpCompleted()
-{
-	LL_DEBUGS("ServerReleaseNotes") << dumpResponse() 
-									<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-
-	std::string location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-	if (location.empty())
-	{
-		location = LLTrans::getString("ErrorFetchingServerReleaseNotesURL");
-	}
-	LLAppViewer::instance()->setServerReleaseNotesURL(location);
-}
-
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index b661fed2760f97dda952ca856ca09b048b51cadb..56619e818af2526f399da48e11796809130da5c5 100755
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -57,6 +57,7 @@
 #include "llsdutil.h"
 #include "llsdutil_math.h"
 #include "lltrans.h"
+#include "llcorehttputil.h"
 
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
@@ -361,7 +362,10 @@ void LLFloaterAuction::doResetParcel()
 
 		LL_INFOS() << "Sending parcel update to reset for auction via capability to: "
 			<< mParcelUpdateCapUrl << LL_ENDL;
-		LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
+
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(mParcelUpdateCapUrl, body,
+            "Parcel reset for auction",
+            "Parcel not set for auction.");
 
 		// Send a message to clear the object return time
 		LLMessageSystem *msg = gMessageSystem;
@@ -490,7 +494,10 @@ void LLFloaterAuction::doSellToAnyone()
 
 		LL_INFOS() << "Sending parcel update to sell to anyone for L$1 via capability to: "
 			<< mParcelUpdateCapUrl << LL_ENDL;
-		LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
+
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(mParcelUpdateCapUrl, body,
+            "Parcel set as sell to everyone.",
+            "Parcel sell to everyone failed.");
 
 		// clean up floater, and get out
 		cleanupAndClose();
diff --git a/indra/newview/llfloaterautoreplacesettings.cpp b/indra/newview/llfloaterautoreplacesettings.cpp
index 6e56e929df606d194bd889db9b4b91c1422b4ebd..5830f2f711cca1f0ddc236b0672a0f9fe7b6b7e2 100755
--- a/indra/newview/llfloaterautoreplacesettings.cpp
+++ b/indra/newview/llfloaterautoreplacesettings.cpp
@@ -36,7 +36,6 @@
 #include "llcolorswatch.h"
 #include "llcombobox.h"
 #include "llview.h"
-#include "llhttpclient.h"
 #include "llbufferstream.h"
 #include "llcheckboxctrl.h"
 #include "llviewercontrol.h"
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 566a3c9cd3950dc4b90241c58312f1a536976f2c..72892b47a492dd38623550c86fa88acfb6200598 100755
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -42,7 +42,6 @@
 #include "llavatarnamecache.h"	// IDEVO
 #include "llbutton.h"
 #include "llcachename.h"
-#include "llhttpclient.h"		// IDEVO
 #include "lllineeditor.h"
 #include "llscrolllistctrl.h"
 #include "llscrolllistitem.h"
@@ -52,6 +51,7 @@
 #include "llfocusmgr.h"
 #include "lldraghandle.h"
 #include "message.h"
+#include "llcorehttputil.h"
 
 //#include "llsdserialize.h"
 
@@ -456,39 +456,33 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
 	return FALSE;
 }
 
-class LLAvatarPickerResponder : public LLHTTPClient::Responder
+/*static*/
+void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::string name)
 {
-	LOG_CLASS(LLAvatarPickerResponder);
-public:
-	LLUUID mQueryID;
-    std::string mName;
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-	LLAvatarPickerResponder(const LLUUID& id, const std::string& name) : mQueryID(id), mName(name) { }
+    LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
 
-protected:
-	/*virtual*/ void httpCompleted()
-	{
-		//std::ostringstream ss;
-		//LLSDSerialize::toPrettyXML(content, ss);
-		//LL_INFOS() << ss.str() << LL_ENDL;
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status || (status == LLCore::HttpStatus(HTTP_BAD_REQUEST)))
+    {
+        LLFloaterAvatarPicker* floater =
+            LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker", name);
+        if (floater)
+        {
+            result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+            floater->processResponse(queryID, result);
+        }
+    }
+}
 
-		// in case of invalid characters, the avatar picker returns a 400
-		// just set it to process so it displays 'not found'
-		if (isGoodStatus() || getStatus() == HTTP_BAD_REQUEST)
-		{
-			LLFloaterAvatarPicker* floater =
-				LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker", mName);
-			if (floater)
-			{
-				floater->processResponse(mQueryID, getContent());
-			}
-		}
-		else
-		{
-			LL_WARNS() << "avatar picker failed " << dumpResponse() << LL_ENDL;
-		}
-	}
-};
 
 void LLFloaterAvatarPicker::find()
 {
@@ -517,7 +511,9 @@ void LLFloaterAvatarPicker::find()
 		std::replace(text.begin(), text.end(), '.', ' ');
 		url += LLURI::escape(text);
 		LL_INFOS() << "avatar picker " << url << LL_ENDL;
-		LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString()));
+
+        LLCoros::instance().launch("LLFloaterAvatarPicker::findCoro",
+            boost::bind(&LLFloaterAvatarPicker::findCoro, url, mQueryID, getKey().asString()));
 	}
 	else
 	{
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index ed3e51c56f163823a8dfdd6fc1c1c4132638672f..fbee61b0549ca432893012322f24735e231f4869 100755
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -28,6 +28,8 @@
 #define LLFLOATERAVATARPICKER_H
 
 #include "llfloater.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 #include <vector>
 
@@ -84,6 +86,7 @@ class LLFloaterAvatarPicker :public LLFloater
 	void populateFriend();
 	BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected.
 
+    static void findCoro(std::string url, LLUUID mQueryID, std::string mName);
 	void find();
 	void setAllowMultiple(BOOL allow_multiple);
 	LLScrollListCtrl* getActiveList();
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index 669ffa7c599814253c6324b38128463aa9a5b55f..e5df417ca9f89d5d8174c6e61d9be7fd3c4f33a4 100755
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -992,20 +992,16 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)
 			{
 				std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString();
 				std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString();
-				LLAssetStorage::LLStoreAssetCallback callback = NULL;
 				S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-				void *userdata = NULL;
-				upload_new_resource(floaterp->mTransactionID, // tid
-						    LLAssetType::AT_ANIMATION,
-						    name,
-						    desc,
-						    0,
-						    LLFolderType::FT_NONE,
-						    LLInventoryType::IT_ANIMATION,
-						    LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
-						    name,
-						    callback, expected_upload_cost, userdata);
 
+                LLResourceUploadInfo::ptr_t assetUpdloadInfo(new LLResourceUploadInfo(
+                    floaterp->mTransactionID, LLAssetType::AT_ANIMATION,
+                    name, desc, 0,
+                    LLFolderType::FT_NONE, LLInventoryType::IT_ANIMATION,
+                    LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
+                    expected_upload_cost));
+
+                upload_new_resource(assetUpdloadInfo);
 			}
 			else
 			{
diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp
deleted file mode 100755
index 596e8c0dbef7b88f7b28dfcf329549926a08d1c9..0000000000000000000000000000000000000000
--- a/indra/newview/llfloaterdisplayname.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/** 
- * @file llfloaterdisplayname.cpp
- * @author Leyla Farazha
- * @brief Implementation of the LLFloaterDisplayName class.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-
-#include "llviewerprecompiledheaders.h"
-#include "llfloaterreg.h"
-#include "llfloater.h"
-
-#include "llnotificationsutil.h"
-#include "llviewerdisplayname.h"
-
-#include "llnotifications.h"
-#include "llfloaterdisplayname.h"
-#include "llavatarnamecache.h"
-
-#include "llagent.h"
-
-
-class LLFloaterDisplayName : public LLFloater
-{
-public:
-	LLFloaterDisplayName(const LLSD& key);
-	virtual ~LLFloaterDisplayName() { }
-	/*virtual*/	BOOL	postBuild();
-	void onSave();
-	void onReset();
-	void onCancel();
-	/*virtual*/ void onOpen(const LLSD& key);
-	
-private:
-	
-	void onCacheSetName(bool success,
-										  const std::string& reason,
-										  const LLSD& content);
-};
-
-LLFloaterDisplayName::LLFloaterDisplayName(const LLSD& key) :
-	LLFloater(key)
-{
-}
-
-void LLFloaterDisplayName::onOpen(const LLSD& key)
-{
-	getChild<LLUICtrl>("display_name_editor")->clear();
-	getChild<LLUICtrl>("display_name_confirm")->clear();
-
-	LLAvatarName av_name;
-	LLAvatarNameCache::get(gAgent.getID(), &av_name);
-
-	F64 now_secs = LLDate::now().secondsSinceEpoch();
-
-	if (now_secs < av_name.mNextUpdate)
-	{
-		// ...can't update until some time in the future
-		F64 next_update_local_secs =
-			av_name.mNextUpdate - LLStringOps::getLocalTimeOffset();
-		LLDate next_update_local(next_update_local_secs);
-		// display as "July 18 12:17 PM"
-		std::string next_update_string =
-		next_update_local.toHTTPDateString("%B %d %I:%M %p");
-		getChild<LLUICtrl>("lockout_text")->setTextArg("[TIME]", next_update_string);
-		getChild<LLUICtrl>("lockout_text")->setVisible(true);
-		getChild<LLUICtrl>("save_btn")->setEnabled(false);
-		getChild<LLUICtrl>("display_name_editor")->setEnabled(false);
-		getChild<LLUICtrl>("display_name_confirm")->setEnabled(false);
-		getChild<LLUICtrl>("cancel_btn")->setFocus(TRUE);
-		
-	}
-	else
-	{
-		getChild<LLUICtrl>("lockout_text")->setVisible(false);
-		getChild<LLUICtrl>("save_btn")->setEnabled(true);
-		getChild<LLUICtrl>("display_name_editor")->setEnabled(true);
-		getChild<LLUICtrl>("display_name_confirm")->setEnabled(true);
-
-	}
-}
-
-BOOL LLFloaterDisplayName::postBuild()
-{
-	getChild<LLUICtrl>("reset_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onReset, this));	
-	getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onCancel, this));	
-	getChild<LLUICtrl>("save_btn")->setCommitCallback(boost::bind(&LLFloaterDisplayName::onSave, this));	
-	
-	center();
-
-	return TRUE;
-}
-
-void LLFloaterDisplayName::onCacheSetName(bool success,
-										  const std::string& reason,
-										  const LLSD& content)
-{
-	if (success)
-	{
-		// Inform the user that the change took place, but will take a while
-		// to percolate.
-		LLSD args;
-		args["DISPLAY_NAME"] = content["display_name"];
-		LLNotificationsUtil::add("SetDisplayNameSuccess", args);
-		return;
-	}
-
-	// Request failed, notify the user
-	std::string error_tag = content["error_tag"].asString();
-	LL_INFOS() << "set name failure error_tag " << error_tag << LL_ENDL;
-
-	// We might have a localized string for this message
-	// error_args will usually be empty from the server.
-	if (!error_tag.empty()
-		&& LLNotifications::getInstance()->templateExists(error_tag))
-	{
-		LLNotificationsUtil::add(error_tag);
-		return;
-	}
-
-	// The server error might have a localized message for us
-	std::string lang_code = LLUI::getLanguage();
-	LLSD error_desc = content["error_description"];
-	if (error_desc.has( lang_code ))
-	{
-		LLSD args;
-		args["MESSAGE"] = error_desc[lang_code].asString();
-		LLNotificationsUtil::add("GenericAlert", args);
-		return;
-	}
-
-	// No specific error, throw a generic one
-	LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
-}
-
-void LLFloaterDisplayName::onCancel()
-{
-	setVisible(false);
-}
-
-void LLFloaterDisplayName::onReset()
-{
-	if (LLAvatarNameCache::hasNameLookupURL())
-	{
-		LLViewerDisplayName::set("",boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3));
-	}	
-	else
-	{
-		LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
-	}
-	
-	setVisible(false);
-}
-
-
-void LLFloaterDisplayName::onSave()
-{
-	std::string display_name_utf8 = getChild<LLUICtrl>("display_name_editor")->getValue().asString();
-	std::string display_name_confirm = getChild<LLUICtrl>("display_name_confirm")->getValue().asString();
-
-	if (display_name_utf8.compare(display_name_confirm))
-	{
-		LLNotificationsUtil::add("SetDisplayNameMismatch");
-		return;
-	}
-
-	const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes
-	LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8);
-	if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH)
-	{
-		LLSD args;
-		args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH);
-		LLNotificationsUtil::add("SetDisplayNameFailedLength", args);
-		return;
-	}
-	
-	if (LLAvatarNameCache::hasNameLookupURL())
-	{
-		LLViewerDisplayName::set(display_name_utf8,boost::bind(&LLFloaterDisplayName::onCacheSetName, this, _1, _2, _3));	
-	}
-	else
-	{
-		LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
-	}
-
-	setVisible(false);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-// LLInspectObjectUtil
-//////////////////////////////////////////////////////////////////////////////
-void LLFloaterDisplayNameUtil::registerFloater()
-{
-	LLFloaterReg::add("display_name", "floater_display_name.xml",
-					  &LLFloaterReg::build<LLFloaterDisplayName>);
-}
diff --git a/indra/newview/llfloaterdisplayname.h b/indra/newview/llfloaterdisplayname.h
deleted file mode 100755
index a00bf56712ce3dfbed1707f92ff971d4cfa71446..0000000000000000000000000000000000000000
--- a/indra/newview/llfloaterdisplayname.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/** 
- * @file llfloaterdisplayname.h
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LLFLOATERDISPLAYNAME_H
-#define LLFLOATERDISPLAYNAME_H
-
-
-namespace LLFloaterDisplayNameUtil
-{
-	// Register with LLFloaterReg
-	void registerFloater();
-}
-
-
-
-#endif
diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp
index 197162487d8998af379717da0d88d7a618741c44..d44eb4310d18fc13106fe2c739bcd89c38535269 100644
--- a/indra/newview/llfloaterexperienceprofile.cpp
+++ b/indra/newview/llfloaterexperienceprofile.cpp
@@ -36,7 +36,6 @@
 #include "llexpandabletextbox.h"
 #include "llexperiencecache.h"
 #include "llfloaterreg.h"
-#include "llhttpclient.h"
 #include "lllayoutstack.h"
 #include "lllineeditor.h"
 #include "llnotificationsutil.h"
@@ -99,7 +98,7 @@ class LLExperienceHandler : public LLCommandHandler
         if(params.size() != 2 || params[1].asString() != "profile")
             return false;
 
-        LLExperienceCache::get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));
+        LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));
         return true;
     }
 
@@ -131,175 +130,20 @@ LLFloaterExperienceProfile::~LLFloaterExperienceProfile()
 
 }
 
-template<class T> 
-class HandleResponder : public LLHTTPClient::Responder
-{
-public:
-    HandleResponder(const LLHandle<T>& parent):mParent(parent){}
-    LLHandle<T> mParent;
-
-    virtual void httpFailure()
-    {
-        LL_WARNS() << "HandleResponder failed with code: " << getStatus() << ", reason: " << getReason() << LL_ENDL;
-    }
-};
-
-class ExperienceUpdateResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
-    ExperienceUpdateResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
-    {
-    }
-
-    virtual void httpSuccess()
-    {
-        LLFloaterExperienceProfile* parent=mParent.get();
-        if(parent)
-        {
-            parent->onSaveComplete(getContent());
-        }
-    }
-};
-
-
-
-class ExperiencePreferencesResponder : public LLHTTPClient::Responder
-{
-public:
-    ExperiencePreferencesResponder(const LLUUID& single = LLUUID::null):mId(single)
-    {
-    }
-
-    bool sendSingle(const LLSD& content, const LLSD& permission, const char* name)
-    {
-        if(!content.has(name))
-            return false;
-
-        LLEventPump& pump = LLEventPumps::instance().obtain("experience_permission");
-        const LLSD& list = content[name];
-        LLSD::array_const_iterator it = list.beginArray();
-        while(it != list.endArray())
-        {
-            if(it->asUUID() == mId)
-            {
-                LLSD message;
-                message[it->asString()] = permission;
-                message["experience"] = mId;
-                pump.post(message);
-                return true;
-            }
-            ++it;
-        }
-        return false;
-    }
-
-    bool hasPermission(const LLSD& content, const char* name)
-    {
-        if(!content.has(name))
-            return false;
-
-        const LLSD& list = content[name];
-        LLSD::array_const_iterator it = list.beginArray();
-        while(it != list.endArray())
-        {
-            if(it->asUUID() == mId)
-            {
-                return true;
-            }
-            ++it;
-        }
-        return false;
-    }
-
-    const char* getPermission(const LLSD& content)
-    {
-        if(hasPermission(content, "experiences"))
-        {
-            return "Allow";
-        }
-        else if(hasPermission(content, "blocked"))
-        {
-            return "Block";
-        }
-        return "Forget";
-    }
-
-
-    virtual void httpSuccess()
-    {
-        if(mId.notNull())
-        {
-            post(getPermission(getContent()));
-            return;
-        }
-        LLEventPumps::instance().obtain("experience_permission").post(getContent());
-    }
-
-    void post( const char* perm )
-    {
-        LLSD experience;
-        LLSD message;
-        experience["permission"]=perm;
-        message["experience"] = mId;
-        message[mId.asString()] = experience;
-        LLEventPumps::instance().obtain("experience_permission").post(message);
-    }
-
-private:
-    LLUUID mId;
-};
-
-
-class IsAdminResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
-    IsAdminResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
-    {
-    }
-    
-    virtual void httpSuccess()
-    {
-        LLFloaterExperienceProfile* parent = mParent.get();
-        if(!parent)
-            return;
-
-        bool enabled = true;
-        LLViewerRegion* region = gAgent.getRegion();
-        if (!region)
-        {
-            enabled = false;
-        }
-        else
-        {
-            std::string url=region->getCapability("UpdateExperience"); 
-            if(url.empty())
-                enabled = false;
-        }
-        if(enabled && getContent()["status"].asBoolean())
-        {
-            parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
-            parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
-        }
-    }
-};
-
 BOOL LLFloaterExperienceProfile::postBuild()
 {
 
     if (mExperienceId.notNull())
     {
-        LLExperienceCache::fetch(mExperienceId, true);
-        LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, 
+        LLExperienceCache::instance().fetch(mExperienceId, true);
+        LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,
             getDerivedHandle<LLFloaterExperienceProfile>(), _1)); 
         
         LLViewerRegion* region = gAgent.getRegion();
         if (region)
         {
-            std::string lookup_url=region->getCapability("IsExperienceAdmin"); 
-            if(!lookup_url.empty())
-            {
-                LLHTTPClient::get(lookup_url+"?experience_id="+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
-            }
+            LLExperienceCache::instance().getExperienceAdmin(mExperienceId, boost::bind(
+                &LLFloaterExperienceProfile::experienceIsAdmin, getDerivedHandle<LLFloaterExperienceProfile>(), _1));
         }
     }
 
@@ -372,23 +216,13 @@ void LLFloaterExperienceProfile::onClickSave()
     doSave(NOTHING);
 }
 
-
 void LLFloaterExperienceProfile::onClickPermission(const char* perm)
 {
     LLViewerRegion* region = gAgent.getRegion();
     if (!region)
         return;
-   
-    std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-    if(lookup_url.empty())
-        return;
-    LLSD permission;
-    LLSD data;
-    permission["permission"]=perm;
-
-    data[mExperienceId.asString()]=permission;
-    LLHTTPClient::put(lookup_url, data, new ExperiencePreferencesResponder(mExperienceId));
-   
+    LLExperienceCache::instance().setExperiencePermission(mExperienceId, perm, boost::bind(
+        &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
 }
 
 
@@ -398,11 +232,8 @@ void LLFloaterExperienceProfile::onClickForget()
     if (!region)
         return;
 
-    std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-    if(lookup_url.empty())
-        return;
-
-    LLHTTPClient::del(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
+    LLExperienceCache::instance().forgetExperiencePermission(mExperienceId, boost::bind(
+        &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
 }
 
 bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo )
@@ -549,11 +380,8 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience )
         LLViewerRegion* region = gAgent.getRegion();
         if (region)
         {
-            std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-            if(!lookup_url.empty())
-            {
-                LLHTTPClient::get(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
-            }
+            LLExperienceCache::instance().getExperiencePermission(mExperienceId, boost::bind(
+                &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
         }
     }
             
@@ -733,15 +561,9 @@ void LLFloaterExperienceProfile::doSave( int success_action )
     if (!region)
         return;
 
-    std::string url=region->getCapability("UpdateExperience"); 
-    if(url.empty())
-        return;
-
-	mPackage.erase(LLExperienceCache::QUOTA);
-	mPackage.erase(LLExperienceCache::EXPIRES);
-	mPackage.erase(LLExperienceCache::AGENT_ID);
-    
-    LLHTTPClient::post(url, mPackage, new ExperienceUpdateResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
+    LLExperienceCache::instance().updateExperience(mPackage, boost::bind(
+            &LLFloaterExperienceProfile::experienceUpdateResult, 
+            getDerivedHandle<LLFloaterExperienceProfile>(), _1));
 }
 
 void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
@@ -799,8 +621,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
     }
  
     refreshExperience(*it);
-    LLExperienceCache::insert(*it);
-    LLExperienceCache::fetch(id, true);
+    LLExperienceCache::instance().insert(*it);
+    LLExperienceCache::instance().fetch(id, true);
 
     if(mSaveCompleteAction==VIEW)
     {
@@ -1002,3 +824,76 @@ void LLFloaterExperienceProfile::onReportExperience()
 {
 	LLFloaterReporter::showFromExperience(mExperienceId);
 }
+
+/*static*/
+bool LLFloaterExperienceProfile::hasPermission(const LLSD& content, const std::string &name, const LLUUID &test)
+{
+    if (!content.has(name))
+        return false;
+
+    const LLSD& list = content[name];
+    LLSD::array_const_iterator it = list.beginArray();
+    while (it != list.endArray())
+    {
+        if (it->asUUID() == test)
+        {
+            return true;
+        }
+        ++it;
+    }
+    return false;
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experiencePermissionResults(LLUUID exprienceId, LLSD result)
+{
+    std::string permission("Forget");
+    if (hasPermission(result, "experiences", exprienceId))
+        permission = "Allow";
+    else if (hasPermission(result, "blocked", exprienceId))
+        permission = "Block";
+
+    LLSD experience;
+    LLSD message;
+    experience["permission"] = permission;
+    message["experience"] = exprienceId;
+    message[exprienceId.asString()] = experience;
+
+    LLEventPumps::instance().obtain("experience_permission").post(message);
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+    LLFloaterExperienceProfile* parent = handle.get();
+    if (!parent)
+        return;
+
+    bool enabled = true;
+    LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        enabled = false;
+    }
+    else
+    {
+        std::string url = region->getCapability("UpdateExperience");
+        if (url.empty())
+            enabled = false;
+    }
+    if (enabled && result["status"].asBoolean())
+    {
+        parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
+        parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
+    }
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+    LLFloaterExperienceProfile* parent = handle.get();
+    if (parent)
+    {
+        parent->onSaveComplete(result);
+    }
+}
diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h
index 78d54eb447b37383537c4b9ffceddc7920052661..7a5ced546b53d18a9b9ef5c811beadd3641ad528 100644
--- a/indra/newview/llfloaterexperienceprofile.h
+++ b/indra/newview/llfloaterexperienceprofile.h
@@ -99,6 +99,12 @@ class LLFloaterExperienceProfile : public LLFloater
     int mSaveCompleteAction;
     bool mDirty;
     bool mForceClose;
+
+private:
+    static bool hasPermission(const LLSD& content, const std::string &name, const LLUUID &test);
+    static void experiencePermissionResults(LLUUID exprienceId, LLSD result);
+    static void experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
+    static void experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
 };
 
 #endif // LL_LLFLOATEREXPERIENCEPROFILE_H
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index 777dc382cd903dc688cce12c62447f08038a5579..fbe00beddd815b9a5525e1e861be66ab01681a96 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -32,7 +32,6 @@
 #include "llevents.h"
 #include "llexperiencecache.h"
 #include "llfloaterregioninfo.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llpanelexperiencelog.h"
 #include "llpanelexperiencepicker.h"
@@ -43,59 +42,6 @@
 
 
 #define SHOW_RECENT_TAB (0)
-
-class LLExperienceListResponder : public LLHTTPClient::Responder
-{
-public:
-    typedef std::map<std::string, std::string> NameMap;
-	typedef boost::function<void(LLPanelExperiences*, const LLSD&)> Callback;
-	LLExperienceListResponder(const LLHandle<LLFloaterExperiences>& parent, NameMap& nameMap, const std::string& errorMessage="ErrorMessage"):mParent(parent),mErrorMessage(errorMessage)
-	{
-		mNameMap.swap(nameMap);
-	}
-
-	Callback mCallback;
-    LLHandle<LLFloaterExperiences> mParent;
-    NameMap mNameMap;
-	const std::string mErrorMessage;
-    /*virtual*/ void httpSuccess()
-    {
-        if(mParent.isDead())
-            return;
-
-        LLFloaterExperiences* parent=mParent.get();
-        LLTabContainer* tabs = parent->getChild<LLTabContainer>("xp_tabs");
- 
-        NameMap::iterator it = mNameMap.begin();
-        while(it != mNameMap.end())
-        {
-            if(getContent().has(it->first))
-            {
-                LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it->second);
-                if(tab)
-                {
-                    const LLSD& ids = getContent()[it->first];
-                    tab->setExperienceList(ids);
-					if(!mCallback.empty())
-					{
-						mCallback(tab, getContent());
-					}
-                }
-            }
-            ++it;
-        }
-    }
-
-	/*virtual*/ void httpFailure()
-	{
-		LLSD subs;
-		subs["ERROR_MESSAGE"] = getReason();
-		LLNotificationsUtil::add(mErrorMessage, subs);
-	}
-};
-
-
-
 LLFloaterExperiences::LLFloaterExperiences(const LLSD& data)
 	:LLFloater(data)
 {
@@ -198,26 +144,20 @@ void LLFloaterExperiences::refreshContents()
 
     if (region)
     {
-        LLExperienceListResponder::NameMap nameMap;
-        std::string lookup_url=region->getCapability("GetExperiences"); 
-        if(!lookup_url.empty())
-        {
-            nameMap["experiences"]="Allowed_Experiences_Tab";
-            nameMap["blocked"]="Blocked_Experiences_Tab";
-            LLHTTPClient::get(lookup_url, new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap));
-        }
+        NameMap_t tabMap;
+        LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
+
+        tabMap["experiences"]="Allowed_Experiences_Tab";
+        tabMap["blocked"]="Blocked_Experiences_Tab";
+        tabMap["experience_ids"]="Owned_Experiences_Tab";
+
+        retrieveExperienceList(region->getCapability("GetExperiences"), handle, tabMap);
 
         updateInfo("GetAdminExperiences","Admin_Experiences_Tab");
         updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
 
-		lookup_url = region->getCapability("AgentExperiences"); 
-		if(!lookup_url.empty())
-		{
-			nameMap["experience_ids"]="Owned_Experiences_Tab";
-			LLExperienceListResponder* responder = new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap, "ExperienceAcquireFailed");
-			responder->mCallback = boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2);
-			LLHTTPClient::get(lookup_url, responder);
-		}
+        retrieveExperienceList(region->getCapability("AgentExperiences"), handle, tabMap, 
+            "ExperienceAcquireFailed", boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2));
     }
 }
 
@@ -303,38 +243,139 @@ void LLFloaterExperiences::checkPurchaseInfo(LLPanelExperiences* panel, const LL
 	LLFloaterExperiences::findInstance()->updateInfo("GetCreatorExperiences","Contrib_Experiences_Tab");
 }
 
-void LLFloaterExperiences::updateInfo(std::string experiences, std::string tab)
+void LLFloaterExperiences::updateInfo(std::string experienceCap, std::string tab)
 {
 	LLViewerRegion* region = gAgent.getRegion();
 	if (region)
 	{
-		LLExperienceListResponder::NameMap nameMap;
-		std::string lookup_url = region->getCapability(experiences);
-		if(!lookup_url.empty())
-		{
-			nameMap["experience_ids"]=tab;
-			LLHTTPClient::get(lookup_url, new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap));
-		}
-	}
+        NameMap_t tabMap;
+        LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
+
+        tabMap["experience_ids"] = tab;
+
+        retrieveExperienceList(region->getCapability(experienceCap), handle, tabMap);
+    }
 }
 
-void LLFloaterExperiences::sendPurchaseRequest() const
+void LLFloaterExperiences::sendPurchaseRequest() 
 {
-	LLViewerRegion* region = gAgent.getRegion();
-	std::string url = region->getCapability("AgentExperiences");
-	if(!url.empty())
-	{
-		LLSD content;
-
-		LLExperienceListResponder::NameMap nameMap;
-		nameMap["experience_ids"]="Owned_Experiences_Tab";
-		LLExperienceListResponder* responder = new LLExperienceListResponder(getDerivedHandle<LLFloaterExperiences>(), nameMap, "ExperienceAcquireFailed");
-		responder->mCallback = boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2);
-		LLHTTPClient::post(url, content, responder);
-	}
+    LLViewerRegion* region = gAgent.getRegion();
+
+    if (region)
+    {
+        NameMap_t tabMap;
+        LLHandle<LLFloaterExperiences> handle = getDerivedHandle<LLFloaterExperiences>();
+
+        tabMap["experience_ids"] = "Owned_Experiences_Tab";
+
+        requestNewExperience(region->getCapability("AgentExperiences"), handle, tabMap, "ExperienceAcquireFailed",
+            boost::bind(&LLFloaterExperiences::checkPurchaseInfo, this, _1, _2));
+    }
 }
 
 LLFloaterExperiences* LLFloaterExperiences::findInstance()
 {
 	return LLFloaterReg::findTypedInstance<LLFloaterExperiences>("experiences");
 }
+
+
+void LLFloaterExperiences::retrieveExperienceList(const std::string &url,
+    const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
+    const std::string &errorNotify, Callback_t cback)
+
+{
+    invokationFn_t getFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> httpOptions
+        // _5 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _4, _5);
+
+    LLCoros::instance().launch("LLFloaterExperiences::retrieveExperienceList",
+        boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
+        url, hparent, tabMapping, errorNotify, cback, getFn));
+
+}
+
+void LLFloaterExperiences::requestNewExperience(const std::string &url,
+    const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
+    const std::string &errorNotify, Callback_t cback)
+{
+    invokationFn_t postFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, const LLSD &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> httpOptions
+        // _5 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, LLSD(), _4, _5);
+
+    LLCoros::instance().launch("LLFloaterExperiences::requestNewExperience",
+        boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
+        url, hparent, tabMapping, errorNotify, cback, postFn));
+
+}
+
+
+void LLFloaterExperiences::retrieveExperienceListCoro(std::string url, 
+    LLHandle<LLFloaterExperiences> hparent, NameMap_t tabMapping, 
+    std::string errorNotify, Callback_t cback, invokationFn_t invoker)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("retrieveExperienceListCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+
+    if (url.empty())
+    {
+        LL_WARNS() << "retrieveExperienceListCoro called with empty capability!" << LL_ENDL;
+        return;
+    }
+
+    LLSD result = invoker(httpAdapter, httpRequest, url, httpOptions, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LLSD subs;
+        subs["ERROR_MESSAGE"] = status.getType();
+        LLNotificationsUtil::add(errorNotify, subs);
+
+        return;
+    }
+
+    if (hparent.isDead())
+        return;
+
+    LLFloaterExperiences* parent = hparent.get();
+    LLTabContainer* tabs = parent->getChild<LLTabContainer>("xp_tabs");
+
+    for (NameMap_t::iterator it = tabMapping.begin(); it != tabMapping.end(); ++it)
+    {
+        if (result.has(it->first))
+        {
+            LLPanelExperiences* tab = (LLPanelExperiences*)tabs->getPanelByName(it->second);
+            if (tab)
+            {
+                const LLSD& ids = result[it->first];
+                tab->setExperienceList(ids);
+                if (!cback.empty())
+                {
+                    cback(tab, result);
+                }
+            }
+        }
+    }
+
+}
diff --git a/indra/newview/llfloaterexperiences.h b/indra/newview/llfloaterexperiences.h
index 769283ff075f9b48f494decf6588f9de415927ef..c038aa63750cfb80010717c328d074ec8a1927c6 100644
--- a/indra/newview/llfloaterexperiences.h
+++ b/indra/newview/llfloaterexperiences.h
@@ -28,6 +28,7 @@
 #define LL_LLFLOATEREXPERIENCES_H
 
 #include "llfloater.h"
+#include "llcorehttputil.h"
 
 class LLPanelExperiences;
 
@@ -41,6 +42,9 @@ class LLFloaterExperiences :
     virtual void onOpen(const LLSD& key);
     static LLFloaterExperiences* findInstance();
 protected:
+    typedef std::map<std::string, std::string> NameMap_t;
+    typedef boost::function<void(LLPanelExperiences*, const LLSD&)> Callback_t;
+
     void clearFromRecent(const LLSD& ids);
     void resizeToTabs();
 	/*virtual*/ BOOL	postBuild();
@@ -49,11 +53,22 @@ class LLFloaterExperiences :
     LLPanelExperiences* addTab(const std::string& name, bool select);
 
     bool updatePermissions(const LLSD& permission);
-	void sendPurchaseRequest() const;
+	void sendPurchaseRequest();
 	void checkPurchaseInfo(LLPanelExperiences* panel, const LLSD& content)const;
 	void updateInfo(std::string experiences, std::string tab);
 
+    void retrieveExperienceList(const std::string &url, const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
+        const std::string &errorNotify = std::string("ErrorMessage"), Callback_t cback = Callback_t());
+
+    void requestNewExperience(const std::string &url, const LLHandle<LLFloaterExperiences> &hparent, const NameMap_t &tabMapping,
+        const std::string &errorNotify, Callback_t cback);
+
 private:
+    typedef boost::function < LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t, LLCore::HttpRequest::ptr_t,
+        const std::string, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) > invokationFn_t;
+
+    static void retrieveExperienceListCoro(std::string url, LLHandle<LLFloaterExperiences> hparent, 
+        NameMap_t tabMapping, std::string errorNotify, Callback_t cback, invokationFn_t invoker);
 
 };
 
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index 37774fbc5c76a95200675cf6e873a99ed1b7fedb..adc7f7158665572dc8b5366d0ef6e6e0a74ce916 100755
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -115,7 +115,7 @@ void LLFloaterGodTools::refreshAll()
 
 LLFloaterGodTools::LLFloaterGodTools(const LLSD& key)
 :	LLFloater(key),
-	mCurrentHost(LLHost::invalid),
+	mCurrentHost(LLHost()),
 	mUpdateTimer()
 {
 	mFactoryMap["grid"] = LLCallbackMap(createPanelGrid, this);
@@ -180,7 +180,7 @@ void LLFloaterGodTools::updatePopup(LLCoordGL center, MASK mask)
 // virtual
 void LLFloaterGodTools::draw()
 {
-	if (mCurrentHost == LLHost::invalid)
+	if (mCurrentHost == LLHost())
 	{
 		if (mUpdateTimer.getElapsedTimeF32() > SECONDS_BETWEEN_UPDATE_REQUESTS)
 		{
@@ -325,7 +325,7 @@ void LLFloaterGodTools::sendRegionInfoRequest()
 {
 	if (mPanelRegionTools) mPanelRegionTools->clearAllWidgets();
 	if (mPanelObjectTools) mPanelObjectTools->clearAllWidgets();
-	mCurrentHost = LLHost::invalid;
+	mCurrentHost = LLHost();
 	mUpdateTimer.reset();
 
 	LLMessageSystem* msg = gMessageSystem;
diff --git a/indra/newview/llfloaterhoverheight.cpp b/indra/newview/llfloaterhoverheight.cpp
index 8908626de6a737aa7cd46ef32ed00f51b76a42ac..003a22fa0418b4c8f921eee56544fb86d56fd815 100755
--- a/indra/newview/llfloaterhoverheight.cpp
+++ b/indra/newview/llfloaterhoverheight.cpp
@@ -31,7 +31,6 @@
 #include "llsliderctrl.h"
 #include "llviewercontrol.h"
 #include "llsdserialize.h"
-#include "llhttpclient.h"
 #include "llagent.h"
 #include "llviewerregion.h"
 #include "llvoavatarself.h"
diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp
index fc7fcf3ab9b3328574a6847787d8bab4f059af04..6623ce0f807ee910d2a150f0c8e4f31565d00d12 100755
--- a/indra/newview/llfloaterimsession.cpp
+++ b/indra/newview/llfloaterimsession.cpp
@@ -41,7 +41,6 @@
 #include "llchicletbar.h"
 #include "lldonotdisturbnotificationstorage.h"
 #include "llfloaterreg.h"
-#include "llhttpclient.h"
 #include "llfloateravatarpicker.h"
 #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container
 #include "llinventoryfunctions.h"
@@ -62,6 +61,7 @@
 #include "llviewerchat.h"
 #include "llnotificationmanager.h"
 #include "llautoreplace.h"
+#include "llcorehttputil.h"
 
 const F32 ME_TYPING_TIMEOUT = 4.0f;
 const F32 OTHER_TYPING_TIMEOUT = 9.0f;
@@ -1178,26 +1178,6 @@ BOOL LLFloaterIMSession::isInviteAllowed() const
 			 || mIsP2PChat);
 }
 
-class LLSessionInviteResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSessionInviteResponder);
-public:
-	LLSessionInviteResponder(const LLUUID& session_id)
-	{
-		mSessionID = session_id;
-	}
-
-protected:
-	void httpFailure()
-	{
-		LL_WARNS() << "Error inviting all agents to session " << dumpResponse() << LL_ENDL;
-		//throw something back to the viewer here?
-	}
-
-private:
-	LLUUID mSessionID;
-};
-
 BOOL LLFloaterIMSession::inviteToSession(const uuid_vec_t& ids)
 {
 	LLViewerRegion* region = gAgent.getRegion();
@@ -1221,7 +1201,9 @@ BOOL LLFloaterIMSession::inviteToSession(const uuid_vec_t& ids)
 			}
 			data["method"] = "invite";
 			data["session-id"] = mSessionID;
-			LLHTTPClient::post(url,	data,new LLSessionInviteResponder(mSessionID));
+
+            LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, data,
+                "Session invite sent", "Session invite failed");
 		}
 		else
 		{
diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp
index b2d36479cd0929c1c894a91440c63e10ccf5b165..18f0bc4498e10c9a6355e70d45dc04da2a141cdb 100755
--- a/indra/newview/llfloatermarketplacelistings.cpp
+++ b/indra/newview/llfloatermarketplacelistings.cpp
@@ -572,7 +572,7 @@ void LLFloaterMarketplaceListings::updateView()
         std::string title;
         std::string tooltip;
     
-        const LLSD& subs = getMarketplaceStringSubstitutions();
+        const LLSD& subs = LLMarketplaceData::getMarketplaceStringSubstitutions();
 
         // Update the top message or flip to the tabs and folders view
         // *TODO : check those messages and create better appropriate ones in strings.xml
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 6804b21b285d872a1002f47757fe6582447233f7..449d5e7d6493ceefe0f3bd172f787f8e0917a2da 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -26,35 +26,8 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#if LL_MSVC
-#pragma warning (disable : 4263)
-#pragma warning (disable : 4264)
-#endif
-#include "dae.h"
-//#include "dom.h"
-#include "dom/domAsset.h"
-#include "dom/domBind_material.h"
-#include "dom/domCOLLADA.h"
-#include "dom/domConstants.h"
-#include "dom/domController.h"
-#include "dom/domEffect.h"
-#include "dom/domGeometry.h"
-#include "dom/domInstance_geometry.h"
-#include "dom/domInstance_material.h"
-#include "dom/domInstance_node.h"
-#include "dom/domInstance_effect.h"
-#include "dom/domMaterial.h"
-#include "dom/domMatrix.h"
-#include "dom/domNode.h"
-#include "dom/domProfile_COMMON.h"
-#include "dom/domRotate.h"
-#include "dom/domScale.h"
-#include "dom/domTranslate.h"
-#include "dom/domVisual_scene.h"
-#if LL_MSVC
-#pragma warning (default : 4263)
-#pragma warning (default : 4264)
-#endif
+#include "llmodelloader.h"
+#include "lldaeloader.h"
 
 #include "llfloatermodelpreview.h"
 
@@ -112,14 +85,15 @@
 #include "llanimationstates.h"
 #include "llviewernetwork.h"
 #include "llviewershadermgr.h"
-#include "glod/glod.h"
 
-const S32 SLM_SUPPORTED_VERSION = 3;
+#include "glod/glod.h"
+#include <boost/algorithm/string.hpp>
 
 //static
 S32 LLFloaterModelPreview::sUploadAmount = 10;
 LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL;
-std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
+
+bool LLModelPreview::sIgnoreLoadedCallback = false;
 
 // "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01
 // But according to the UI spec for upload model floater, this parameter
@@ -199,190 +173,46 @@ std::string lod_label_name[NUM_LOD+1] =
 	"I went off the end of the lod_label_name array.  Me so smart."
 };
 
-std::string colladaVersion[VERSIONTYPE_COUNT+1] = 
-{
-	"1.4.0",
-	"1.4.1",
-	"Unsupported"
-};
-
-
-#define LL_DEGENERACY_TOLERANCE  1e-7f
-
-inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
-{
-    volatile F32 p0 = a[0] * b[0];
-    volatile F32 p1 = a[1] * b[1];
-    volatile F32 p2 = a[2] * b[2];
-    return p0 + p1 + p2;
-}
-
-bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
-{
-        // small area check
-        {
-                LLVector4a edge1; edge1.setSub( a, b );
-                LLVector4a edge2; edge2.setSub( a, c );
-                //////////////////////////////////////////////////////////////////////////
-                /// Linden Modified
-                //////////////////////////////////////////////////////////////////////////
-
-                // If no one edge is more than 10x longer than any other edge, we weaken
-                // the tolerance by a factor of 1e-4f.
-
-                LLVector4a edge3; edge3.setSub( c, b );
-				const F32 len1sq = edge1.dot3(edge1).getF32();
-                const F32 len2sq = edge2.dot3(edge2).getF32();
-                const F32 len3sq = edge3.dot3(edge3).getF32();
-                bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
-                bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
-                bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
-                if ( abOK && acOK && cbOK )
-                {
-                        tolerance *= 1e-4f;
-                }
-
-                //////////////////////////////////////////////////////////////////////////
-                /// End Modified
-                //////////////////////////////////////////////////////////////////////////
-
-                LLVector4a cross; cross.setCross3( edge1, edge2 );
-
-                LLVector4a edge1b; edge1b.setSub( b, a );
-                LLVector4a edge2b; edge2b.setSub( b, c );
-                LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
-
-                if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
-                {
-                        return true;
-                }
-        }
-
-        // point triangle distance check
-        {
-                LLVector4a Q; Q.setSub(a, b);
-                LLVector4a R; R.setSub(c, b);
-
-                const F32 QQ = dot3fpu(Q, Q);
-                const F32 RR = dot3fpu(R, R);
-                const F32 QR = dot3fpu(R, Q);
-
-                volatile F32 QQRR = QQ * RR;
-                volatile F32 QRQR = QR * QR;
-                F32 Det = (QQRR - QRQR);
-
-                if( Det == 0.0f )
-                {
-                        return true;
-                }
-        }
-
-        return false;
-}
-
-bool validate_face(const LLVolumeFace& face)
+BOOL stop_gloderror()
 {
+	GLuint error = glodGetError();
 
-	for (U32 v = 0; v < face.mNumVertices; v++)
-	{
-		if(face.mPositions && !face.mPositions[v].isFinite3())
-		{
-			LL_WARNS() << "NaN position data in face found!" << LL_ENDL;
-			return false;
-		}
-
-		if(face.mNormals && !face.mNormals[v].isFinite3())
-		{
-			LL_WARNS() << "NaN normal data in face found!" << LL_ENDL;
-			return false;
-		}
-	}
-
-	for (U32 i = 0; i < face.mNumIndices; ++i)
-	{
-		if (face.mIndices[i] >= face.mNumVertices)
-		{
-			LL_WARNS() << "Face has invalid index." << LL_ENDL;
-			return false;
-		}
-	}
-
-	if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+	if (error != GLOD_NO_ERROR)
 	{
-		LL_WARNS() << "Face has invalid number of indices." << LL_ENDL;
-		return false;
+		LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
+		return TRUE;
 	}
 
-
-	/*const LLVector4a scale(0.5f);
-
-
-	for (U32 i = 0; i < face.mNumIndices; i+=3)
-	{
-		U16 idx1 = face.mIndices[i];
-		U16 idx2 = face.mIndices[i+1];
-		U16 idx3 = face.mIndices[i+2];
-
-		LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
-		LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
-		LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
-
-		if (ll_is_degenerate(v1,v2,v3))
-		{
-			LL_WARNS() << "Degenerate face found!" << LL_ENDL;
-			return false;
-		}
-	}*/
-	return true;
+	return FALSE;
 }
 
-bool validate_model(const LLModel* mdl)
+LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
 {
-	if (mdl->getNumVolumeFaces() == 0)
-	{
-		LL_WARNS() << "Model has no faces!" << LL_ENDL;
-		return false;
-	}
+	LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
 
-	for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+	if (texture)
 	{
-		if (mdl->getVolumeFace(i).mNumVertices == 0)
-		{
-			LL_WARNS() << "Face has no vertices." << LL_ENDL;
-			return false;
-		}
-
-		if (mdl->getVolumeFace(i).mNumIndices == 0)
-		{
-			LL_WARNS() << "Face has no indices." << LL_ENDL;
-			return false;
-		}
-
-		if (!validate_face(mdl->getVolumeFace(i)))
+		if (texture->getDiscardLevel() > -1)
 		{
-			return false;
+			gGL.getTexUnit(0)->bind(texture, true);
+			return texture;
 		}
 	}
 
-	return true;
+	return NULL;
 }
 
-BOOL stop_gloderror()
+std::string stripSuffix(std::string name)
 {
-	GLuint error = glodGetError();
-
-	if (error != GLOD_NO_ERROR)
+	if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1))
 	{
-		LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
-		return TRUE;
+		return name.substr(0, name.rfind('_'));
 	}
-
-	return FALSE;
+	return name;
 }
 
-
 LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
-	: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
+: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
 	{
 		mMP = mp;
 		mLOD = lod;
@@ -393,6 +223,29 @@ void LLMeshFilePicker::notify(const std::string& filename)
 	mMP->loadModel(mFile, mLOD);
 }
 
+void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
+{
+    LLModelLoader::scene::iterator base_iter = scene.begin();
+    bool found = false;
+    while (!found && (base_iter != scene.end()))
+    {
+        matOut = base_iter->first;
+
+        LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin();
+        while (!found && (base_instance_iter != base_iter->second.end()))
+        {
+		    LLModelInstance& base_instance = *base_instance_iter++;					    		    
+            LLModel* base_model = base_instance.mModel;
+         
+            if (base_model && (base_model->mLabel == name_to_match))
+            {
+                baseModelOut = base_model;
+                return;
+            }
+        }
+        base_iter++;
+    }
+}
 
 //-----------------------------------------------------------------------------
 // LLFloaterModelPreview()
@@ -613,6 +466,11 @@ void LLFloaterModelPreview::disableViewOption(const std::string& option)
 void LLFloaterModelPreview::loadModel(S32 lod)
 {
 	mModelPreview->mLoading = true;
+	if (lod == LLModel::LOD_PHYSICS)
+	{
+		// loading physics from file
+		mModelPreview->mPhysicsSearchLOD = lod;
+	}
 
 	(new LLMeshFilePicker(mModelPreview, lod))->getFile();
 }
@@ -791,9 +649,9 @@ void LLFloaterModelPreview::draw()
 			childSetTextArg("status", "[STATUS]", getString("status_material_mismatch"));
 		}
 		else
-		if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING )
-		{		
-			childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING)));
+		if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_MODEL )
+		{
+			childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_MODEL)));
 		}
 		else
 		if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
@@ -945,9 +803,16 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
 /*virtual*/
 void LLFloaterModelPreview::onOpen(const LLSD& key)
 {
+	LLModelPreview::sIgnoreLoadedCallback = false;
 	requestAgentUploadPermissions();
 }
 
+/*virtual*/
+void LLFloaterModelPreview::onClose(bool app_quitting)
+{
+	LLModelPreview::sIgnoreLoadedCallback = true;
+}
+
 //static
 void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)
 {
@@ -1308,2033 +1173,197 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
 }
 
 //-----------------------------------------------------------------------------
-// LLModelLoader
+// LLModelPreview
 //-----------------------------------------------------------------------------
-LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
-							  std::deque<std::string>& jointsFromNodes )
-: mJointList( jointMap )
-, mJointsFromNode( jointsFromNodes )
-, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0)
+
+LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
+: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
+, mPelvisZOffset( 0.0f )
+, mLegacyRigValid( false )
+, mRigValidJointUpload( false )
+, mPhysicsSearchLOD( LLModel::LOD_PHYSICS )
+, mResetJoints( false )
+, mModelNoErrors( true )
+, mRigParityWithScene( false )
+, mLastJointUpdate( false )
 {
-	mJointMap["mPelvis"] = "mPelvis";
-	mJointMap["mTorso"] = "mTorso";
-	mJointMap["mChest"] = "mChest";
-	mJointMap["mNeck"] = "mNeck";
-	mJointMap["mHead"] = "mHead";
-	mJointMap["mSkull"] = "mSkull";
-	mJointMap["mEyeRight"] = "mEyeRight";
-	mJointMap["mEyeLeft"] = "mEyeLeft";
-	mJointMap["mCollarLeft"] = "mCollarLeft";
-	mJointMap["mShoulderLeft"] = "mShoulderLeft";
-	mJointMap["mElbowLeft"] = "mElbowLeft";
-	mJointMap["mWristLeft"] = "mWristLeft";
-	mJointMap["mCollarRight"] = "mCollarRight";
-	mJointMap["mShoulderRight"] = "mShoulderRight";
-	mJointMap["mElbowRight"] = "mElbowRight";
-	mJointMap["mWristRight"] = "mWristRight";
-	mJointMap["mHipRight"] = "mHipRight";
-	mJointMap["mKneeRight"] = "mKneeRight";
-	mJointMap["mAnkleRight"] = "mAnkleRight";
-	mJointMap["mFootRight"] = "mFootRight";
-	mJointMap["mToeRight"] = "mToeRight";
-	mJointMap["mHipLeft"] = "mHipLeft";
-	mJointMap["mKneeLeft"] = "mKneeLeft";
-	mJointMap["mAnkleLeft"] = "mAnkleLeft";
-	mJointMap["mFootLeft"] = "mFootLeft";
-	mJointMap["mToeLeft"] = "mToeLeft";
-
-	mJointMap["avatar_mPelvis"] = "mPelvis";
-	mJointMap["avatar_mTorso"] = "mTorso";
-	mJointMap["avatar_mChest"] = "mChest";
-	mJointMap["avatar_mNeck"] = "mNeck";
-	mJointMap["avatar_mHead"] = "mHead";
-	mJointMap["avatar_mSkull"] = "mSkull";
-	mJointMap["avatar_mEyeRight"] = "mEyeRight";
-	mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
-	mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
-	mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
-	mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
-	mJointMap["avatar_mWristLeft"] = "mWristLeft";
-	mJointMap["avatar_mCollarRight"] = "mCollarRight";
-	mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
-	mJointMap["avatar_mElbowRight"] = "mElbowRight";
-	mJointMap["avatar_mWristRight"] = "mWristRight";
-	mJointMap["avatar_mHipRight"] = "mHipRight";
-	mJointMap["avatar_mKneeRight"] = "mKneeRight";
-	mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
-	mJointMap["avatar_mFootRight"] = "mFootRight";
-	mJointMap["avatar_mToeRight"] = "mToeRight";
-	mJointMap["avatar_mHipLeft"] = "mHipLeft";
-	mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
-	mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
-	mJointMap["avatar_mFootLeft"] = "mFootLeft";
-	mJointMap["avatar_mToeLeft"] = "mToeLeft";
-
-
-	mJointMap["hip"] = "mPelvis";
-	mJointMap["abdomen"] = "mTorso";
-	mJointMap["chest"] = "mChest";
-	mJointMap["neck"] = "mNeck";
-	mJointMap["head"] = "mHead";
-	mJointMap["figureHair"] = "mSkull";
-	mJointMap["lCollar"] = "mCollarLeft";
-	mJointMap["lShldr"] = "mShoulderLeft";
-	mJointMap["lForeArm"] = "mElbowLeft";
-	mJointMap["lHand"] = "mWristLeft";
-	mJointMap["rCollar"] = "mCollarRight";
-	mJointMap["rShldr"] = "mShoulderRight";
-	mJointMap["rForeArm"] = "mElbowRight";
-	mJointMap["rHand"] = "mWristRight";
-	mJointMap["rThigh"] = "mHipRight";
-	mJointMap["rShin"] = "mKneeRight";
-	mJointMap["rFoot"] = "mFootRight";
-	mJointMap["lThigh"] = "mHipLeft";
-	mJointMap["lShin"] = "mKneeLeft";
-	mJointMap["lFoot"] = "mFootLeft";
-
-	if (mPreview)
-	{
-		//only try to load from slm if viewer is configured to do so and this is the 
-		//initial model load (not an LoD or physics shape)
-		mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty();
-		mPreview->setLoadState(STARTING);
-	}
-	else
+	mNeedsUpdate = TRUE;
+	mCameraDistance = 0.f;
+	mCameraYaw = 0.f;
+	mCameraPitch = 0.f;
+	mCameraZoom = 1.f;
+	mTextureName = 0;
+	mPreviewLOD = 0;
+	mModelLoader = NULL;
+	mMaxTriangleLimit = 0;
+	mDirty = false;
+	mGenLOD = false;
+	mLoading = false;
+	mLoadState = LLModelLoader::STARTING;
+	mGroup = 0;
+	mLODFrozen = false;
+	mBuildShareTolerance = 0.f;
+	mBuildQueueMode = GLOD_QUEUE_GREEDY;
+	mBuildBorderMode = GLOD_BORDER_UNLOCK;
+	mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE;
+
+	for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
 	{
-		mTrySLM = false;
+		mRequestedTriangleCount[i] = 0;
+		mRequestedCreaseAngle[i] = -1.f;
+		mRequestedLoDMode[i] = 0;
+		mRequestedErrorThreshold[i] = 0.f;
+		mRequestedBuildOperator[i] = 0;
+		mRequestedQueueMode[i] = 0;
+		mRequestedBorderMode[i] = 0;
+		mRequestedShareTolerance[i] = 0.f;
 	}
 
-	assert_main_thread();
-	sActiveLoaderList.push_back(this) ;
+	mViewOption["show_textures"] = false;
+
+	mFMP = fmp;
+
+	mHasPivot = false;
+	mModelPivot = LLVector3( 0.0f, 0.0f, 0.0f );
+	
+	glodInit();
+
+	createPreviewAvatar();
 }
 
-LLModelLoader::~LLModelLoader()
+LLModelPreview::~LLModelPreview()
 {
-	assert_main_thread();
-	sActiveLoaderList.remove(this);
+	// glod apparently has internal mem alignment issues that are angering
+	// the heap-check code in windows, these should be hunted down in that
+	// TP code, if possible
+	//
+	// kernel32.dll!HeapFree()  + 0x14 bytes	
+	// msvcr100.dll!free(void * pBlock)  Line 51	C
+	// glod.dll!glodGetGroupParameteriv()  + 0x119 bytes	
+	// glod.dll!glodShutdown()  + 0x77 bytes	
+	//
+	//glodShutdown();
 }
 
-void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
+U32 LLModelPreview::calcResourceCost()
 {
-	LLVector4a box[] =
-	{
-		LLVector4a(-1, 1,-1),
-		LLVector4a(-1, 1, 1),
-		LLVector4a(-1,-1,-1),
-		LLVector4a(-1,-1, 1),
-		LLVector4a( 1, 1,-1),
-		LLVector4a( 1, 1, 1),
-		LLVector4a( 1,-1,-1),
-		LLVector4a( 1,-1, 1),
-	};
-
-	for (S32 j = 0; j < model->getNumVolumeFaces(); ++j)
-	{
-		const LLVolumeFace& face = model->getVolumeFace(j);
+	assert_main_thread();
 
-		LLVector4a center;
-		center.setAdd(face.mExtents[0], face.mExtents[1]);
-		center.mul(0.5f);
-		LLVector4a size;
-		size.setSub(face.mExtents[1],face.mExtents[0]);
-		size.mul(0.5f);
+	rebuildUploadData();
 
-		for (U32 i = 0; i < 8; i++)
+	//Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
+	if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
+	{
+		bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+		if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
 		{
-			LLVector4a t;
-			t.setMul(size, box[i]);
-			t.add(center);
+			mFMP->childDisable("ok_btn");		
+		}		
+	}
+	
+	std::set<LLModel*> accounted;
+	U32 num_points = 0;
+	U32 num_hulls = 0;
 
-			LLVector4a v;
+	F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f;
+	mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f;
+	
+	if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() )
+	{
+		// FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail.
+		// see also call to addAttachmentPosOverride.
+		LLUUID fake_mesh_id;
+		fake_mesh_id.generate();
+		getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id );
+	}
 
-			mat.affineTransform(t, v);
+	F32 streaming_cost = 0.f;
+	F32 physics_cost = 0.f;
+	for (U32 i = 0; i < mUploadData.size(); ++i)
+	{
+		LLModelInstance& instance = mUploadData[i];
+		
+		if (accounted.find(instance.mModel) == accounted.end())
+		{
+			accounted.insert(instance.mModel);
 
-			if (first_transform)
-			{
-				first_transform = FALSE;
-				min = max = v;
+			LLModel::Decomposition& decomp =
+			instance.mLOD[LLModel::LOD_PHYSICS] ?
+			instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
+			instance.mModel->mPhysics;
+			
+			//update instance skin info for each lods pelvisZoffset 
+			for ( int j=0; j<LLModel::NUM_LODS; ++j )
+			{	
+				if ( instance.mLOD[j] )
+				{
+					instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;
+				}
 			}
-			else
+
+			std::stringstream ostr;
+			LLSD ret = LLModel::writeModel(ostr,
+					   instance.mLOD[4],
+					   instance.mLOD[3],
+					   instance.mLOD[2],
+					   instance.mLOD[1],
+					   instance.mLOD[0],
+					   decomp,
+					   mFMP->childGetValue("upload_skin").asBoolean(),
+					   mFMP->childGetValue("upload_joints").asBoolean(),
+					   TRUE,
+						FALSE,
+						instance.mModel->mSubmodelID);
+			
+			num_hulls += decomp.mHull.size();
+			for (U32 i = 0; i < decomp.mHull.size(); ++i)
 			{
-				update_min_max(min, max, v);
+				num_points += decomp.mHull[i].size();
 			}
+
+			//calculate streaming cost
+			LLMatrix4 transformation = instance.mTransform;
+
+			LLVector3 position = LLVector3(0, 0, 0) * transformation;
+
+			LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
+			LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
+			LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
+			F32 x_length = x_transformed.normalize();
+			F32 y_length = y_transformed.normalize();
+			F32 z_length = z_transformed.normalize();
+			LLVector3 scale = LLVector3(x_length, y_length, z_length);
+
+			F32 radius = scale.length()*0.5f*debug_scale;
+
+			streaming_cost += LLMeshRepository::getStreamingCost(ret, radius);
 		}
 	}
-}
 
-void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
-{
-	LLVector4a mina, maxa;
-	LLMatrix4a mata;
+	F32 scale = mFMP ? mFMP->childGetValue("import_scale").asReal()*2.f : 2.f;
 
-	mata.loadu(mat);
-	mina.load3(min.mV);
-	maxa.load3(max.mV);
+	mDetailsSignal(mPreviewScale[0]*scale, mPreviewScale[1]*scale, mPreviewScale[2]*scale, streaming_cost, physics_cost);
 
-	stretch_extents(model, mata, mina, maxa, first_transform);
+	updateStatusMessages();
 
-	min.set(mina.getF32ptr());
-	max.set(maxa.getF32ptr());
+	return (U32) streaming_cost;
 }
 
-void LLModelLoader::run()
+void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
 {
-	doLoadModel();
-	doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
+	assert_main_thread();
+	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
+	childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
+	childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
 }
 
-bool LLModelLoader::doLoadModel()
+
+void LLModelPreview::rebuildUploadData()
 {
-	//first, look for a .slm file of the same name that was modified later
-	//than the .dae
+	assert_main_thread();
 
-	if (mTrySLM)
-	{
-		std::string filename = mFilename;
-			
-		std::string::size_type i = filename.rfind(".");
-		if (i != std::string::npos)
-		{
-			filename.replace(i, filename.size()-1, ".slm");
-			llstat slm_status;
-			if (LLFile::stat(filename, &slm_status) == 0)
-			{ //slm file exists
-				llstat dae_status;
-				if (LLFile::stat(mFilename, &dae_status) != 0 ||
-					dae_status.st_mtime < slm_status.st_mtime)
-				{
-					if (loadFromSLM(filename))
-					{ //slm successfully loaded, if this fails, fall through and
-						//try loading from dae
-
-						mLod = -1; //successfully loading from an slm implicitly sets all 
-									//LoDs
-						return true;
-					}
-				}
-			}	
-		}
-	}
-
-	//no suitable slm exists, load from the .dae file
-	DAE dae;
-	domCOLLADA* dom = dae.open(mFilename);
-	
-	if (!dom)
-	{
-		LL_INFOS()<<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL;
-		setLoadState( ERROR_PARSING );
-		return false;
-	}
-	//Dom version
-	daeString domVersion = dae.getDomVersion();
-	std::string sldom(domVersion);
-	LL_INFOS()<<"Collada Importer Version: "<<sldom<<LL_ENDL;
-	//Dae version
-	domVersionType docVersion = dom->getVersion();
-	//0=1.4
-	//1=1.4.1
-	//2=Currently unsupported, however may work
-	if (docVersion > 1 ) 
-	{ 
-		docVersion = VERSIONTYPE_COUNT;
-	}
-	LL_INFOS()<<"Dae version "<<colladaVersion[docVersion]<<LL_ENDL;
-	
-	
-	daeDatabase* db = dae.getDatabase();
-	
-	daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
-	
-	daeDocument* doc = dae.getDoc(mFilename);
-	if (!doc)
-	{
-		LL_WARNS() << "can't find internal doc" << LL_ENDL;
-		return false;
-	}
-	
-	daeElement* root = doc->getDomRoot();
-	if (!root)
-	{
-		LL_WARNS() << "document has no root" << LL_ENDL;
-		return false;
-	}
-	
-	//Verify some basic properties of the dae
-	//1. Basic validity check on controller 
-	U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
-	bool result = false;
-	for ( int i=0; i<controllerCount; ++i )
-	{
-		domController* pController = NULL;
-		db->getElement( (daeElement**) &pController, i , NULL, "controller" );
-		result = mPreview->verifyController( pController );
-		if (!result)
-		{
-			setLoadState( ERROR_PARSING );
-			return true;
-		}
-	}
-
-
-	//get unit scale
-	mTransform.setIdentity();
-	
-	domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID())));
-	
-	if (unit)
-	{
-		F32 meter = unit->getMeter();
-		mTransform.mMatrix[0][0] = meter;
-		mTransform.mMatrix[1][1] = meter;
-		mTransform.mMatrix[2][2] = meter;
-	}
-	
-	//get up axis rotation
-	LLMatrix4 rotation;
-	
-	domUpAxisType up = UPAXISTYPE_Y_UP;  // default is Y_UP
-	domAsset::domUp_axis* up_axis =
-	daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID())));
-	
-	if (up_axis)
-	{
-		up = up_axis->getValue();
-	}
-	
-	if (up == UPAXISTYPE_X_UP)
-	{
-		rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
-	}
-	else if (up == UPAXISTYPE_Y_UP)
-	{
-		rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
-	}
-	
-	rotation *= mTransform;
-	mTransform = rotation;
-	
-	
-	for (daeInt idx = 0; idx < count; ++idx)
-	{ //build map of domEntities to LLModel
-		domMesh* mesh = NULL;
-		db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
-		
-		if (mesh)
-		{
-			LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh);
-			
-			if(model->getStatus() != LLModel::NO_ERRORS)
-			{
-				setLoadState(ERROR_PARSING + model->getStatus()) ;
-				return false; //abort
-			}
-
-			if (model.notNull() && validate_model(model))
-			{
-				mModelList.push_back(model);
-				mModel[mesh] = model;
-			}
-		}
-	}
-	
-	count = db->getElementCount(NULL, COLLADA_TYPE_SKIN);
-	for (daeInt idx = 0; idx < count; ++idx)
-	{ //add skinned meshes as instances
-		domSkin* skin = NULL;
-		db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
-		
-		if (skin)
-		{
-			domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
-			
-			if (geom)
-			{
-				domMesh* mesh = geom->getMesh();
-				if (mesh)
-				{
-					LLModel* model = mModel[mesh];
-					if (model)
-					{
-						LLVector3 mesh_scale_vector;
-						LLVector3 mesh_translation_vector;
-						model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-						
-						LLMatrix4 normalized_transformation;
-						normalized_transformation.setTranslation(mesh_translation_vector);
-						
-						LLMatrix4 mesh_scale;
-						mesh_scale.initScale(mesh_scale_vector);
-						mesh_scale *= normalized_transformation;
-						normalized_transformation = mesh_scale;
-						
-						glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
-						inv_mat = inv_mat.inverse();
-						LLMatrix4 inverse_normalized_transformation(inv_mat.m);
-						
-						domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
-						
-						if (bind_mat)
-						{ //get bind shape matrix
-							domFloat4x4& dom_value = bind_mat->getValue();
-							
-							LLMeshSkinInfo& skin_info = model->mSkinInfo;
-
-							for (int i = 0; i < 4; i++)
-							{
-								for(int j = 0; j < 4; j++)
-								{
-									skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
-								}
-							}
-							
-							LLMatrix4 trans = normalized_transformation;
-							trans *= skin_info.mBindShapeMatrix;
-							skin_info.mBindShapeMatrix = trans;							
-						}
-										
-											
-						//Some collada setup for accessing the skeleton
-						daeElement* pElement = 0;
-						dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
-						
-						//Try to get at the skeletal instance controller
-						domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
-						bool missingSkeletonOrScene = false;
-						
-						//If no skeleton, do a breadth-first search to get at specific joints
-						bool rootNode = false;
-						
-						//Need to test for a skeleton that does not have a root node
-						//This occurs when your instance controller does not have an associated scene 
-						if ( pSkeleton )
-						{
-							daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
-							if ( pSkeletonRootNode )
-							{
-								rootNode = true;
-							}
-
-						}
-						if ( !pSkeleton || !rootNode )
-						{
-							daeElement* pScene = root->getDescendant("visual_scene");
-							if ( !pScene )
-							{
-								LL_WARNS()<<"No visual scene - unable to parse bone offsets "<<LL_ENDL;
-								missingSkeletonOrScene = true;
-							}
-							else
-							{
-								//Get the children at this level
-								daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
-								S32 childCount = children.getCount();
-								
-								//Process any children that are joints
-								//Not all children are joints, some code be ambient lights, cameras, geometry etc..
-								for (S32 i = 0; i < childCount; ++i)
-								{
-									domNode* pNode = daeSafeCast<domNode>(children[i]);
-									if ( isNodeAJoint( pNode ) )
-									{
-										processJointNode( pNode, mJointList );
-									}
-								}
-							}
-						}
-						else
-							//Has Skeleton
-						{
-							//Get the root node of the skeleton
-							daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
-							if ( pSkeletonRootNode )
-							{
-								//Once we have the root node - start acccessing it's joint components
-								const int jointCnt = mJointMap.size();
-								std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin();
-								
-								//Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
-								for ( int i=0; i<jointCnt; ++i, ++jointIt )
-								{
-									//Build a joint for the resolver to work with
-									char str[64]={0};
-									sprintf(str,"./%s",(*jointIt).first.c_str() );
-									//LL_WARNS()<<"Joint "<< str <<LL_ENDL;
-									
-									//Setup the resolver
-                                    daeSIDResolver resolver( pSkeletonRootNode, str );
-									
-                                    //Look for the joint
-                                    domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
-                                    if ( pJoint )
-                                    {
-										//Pull out the translate id and store it in the jointTranslations map
-										daeSIDResolver jointResolverA( pJoint, "./translate" );
-										domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
-										daeSIDResolver jointResolverB( pJoint, "./location" );
-										domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
-										
-										LLMatrix4 workingTransform;
-										
-										//Translation via SID
-										if ( pTranslateA )
-										{
-											extractTranslation( pTranslateA, workingTransform );
-										}
-										else
-										if ( pTranslateB )
-										{
-											extractTranslation( pTranslateB, workingTransform );
-										}
-										else
-										{
-											//Translation via child from element
-											daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" );
-											if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() )
-											{
-												LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
-												missingSkeletonOrScene = true;
-											}
-											else
-											if ( pTranslateElement )
-											{
-												extractTranslationViaElement( pTranslateElement, workingTransform );
-											}
-											else
-											{
-												extractTranslationViaSID( pJoint, workingTransform );
-											}
-
-										}
-										
-										//Store the joint transform w/respect to it's name.
-										mJointList[(*jointIt).second.c_str()] = workingTransform;
-                                    }
-								}
-								
-								//If anything failed in regards to extracting the skeleton, joints or translation id,
-								//mention it
-								if ( missingSkeletonOrScene  )
-								{
-									LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL;
-								}
-							}//got skeleton?
-						}
-						
-						
-						domSkin::domJoints* joints = skin->getJoints();
-						
-						domInputLocal_Array& joint_input = joints->getInput_array();
-						
-						for (size_t i = 0; i < joint_input.getCount(); ++i)
-						{
-							domInputLocal* input = joint_input.get(i);
-							xsNMTOKEN semantic = input->getSemantic();
-							
-							if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0)
-							{ //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames
-								daeElement* elem = input->getSource().getElement();
-								
-								domSource* source = daeSafeCast<domSource>(elem);
-								if (source)
-								{
-									
-									
-									domName_array* names_source = source->getName_array();
-									
-									if (names_source)
-									{
-										domListOfNames &names = names_source->getValue();
-										
-										for (size_t j = 0; j < names.getCount(); ++j)
-										{
-											std::string name(names.get(j));
-											if (mJointMap.find(name) != mJointMap.end())
-											{
-												name = mJointMap[name];
-											}
-											model->mSkinInfo.mJointNames.push_back(name);
-											model->mSkinInfo.mJointMap[name] = j;
-										}
-									}
-									else
-									{
-										domIDREF_array* names_source = source->getIDREF_array();
-										if (names_source)
-										{
-											xsIDREFS& names = names_source->getValue();
-											
-											for (size_t j = 0; j < names.getCount(); ++j)
-											{
-												std::string name(names.get(j).getID());
-												if (mJointMap.find(name) != mJointMap.end())
-												{
-													name = mJointMap[name];
-												}
-												model->mSkinInfo.mJointNames.push_back(name);
-												model->mSkinInfo.mJointMap[name] = j;
-											}
-										}
-									}
-								}
-							}
-							else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0)
-							{ //found inv_bind_matrix array, fill model->mInvBindMatrix
-								domSource* source = daeSafeCast<domSource>(input->getSource().getElement());
-								if (source)
-								{
-									domFloat_array* t = source->getFloat_array();
-									if (t)
-									{
-										domListOfFloats& transform = t->getValue();
-										S32 count = transform.getCount()/16;
-										
-										for (S32 k = 0; k < count; ++k)
-										{
-											LLMatrix4 mat;
-											
-											for (int i = 0; i < 4; i++)
-											{
-												for(int j = 0; j < 4; j++)
-												{
-													mat.mMatrix[i][j] = transform[k*16 + i + j*4];
-												}
-											}
-											
-											model->mSkinInfo.mInvBindMatrix.push_back(mat);											
-										}
-									}
-								}
-							}
-						}
-						
-						//Now that we've parsed the joint array, let's determine if we have a full rig
-						//(which means we have all the joint sthat are required for an avatar versus
-						//a skinned asset attached to a node in a file that contains an entire skeleton,
-						//but does not use the skeleton).						
-						buildJointToNodeMappingFromScene( root );
-						mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames );
-										
-						if ( !missingSkeletonOrScene )
-						{
-							//Set the joint translations on the avatar - if it's a full mapping
-							//The joints are reset in the dtor
-							if ( mPreview->getRigWithSceneParity() )
-							{	
-								std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin();
-								std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end();
-								for (;masterJointIt!=masterJointItEnd;++masterJointIt )
-								{
-									std::string lookingForJoint = (*masterJointIt).first.c_str();
-									
-									if ( mJointList.find( lookingForJoint ) != mJointList.end() )
-									{
-										//LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL;
-										LLMatrix4 jointTransform = mJointList[lookingForJoint];
-										LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint );
-										if ( pJoint )
-										{   
-											LLUUID fake_mesh_id;
-											fake_mesh_id.generate();
-											pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, gAgentAvatarp->avString());
-										}
-										else
-										{
-											//Most likely an error in the asset.
-											LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL;
-										}
-									}
-								}
-							}
-						} //missingSkeletonOrScene
-						
-						
-						//We need to construct the alternate bind matrix (which contains the new joint positions)
-						//in the same order as they were stored in the joint buffer. The joints associated
-						//with the skeleton are not stored in the same order as they are in the exported joint buffer.
-						//This remaps the skeletal joints to be in the same order as the joints stored in the model.
-						std::vector<std::string> :: const_iterator jointIt  = model->mSkinInfo.mJointNames.begin();
-						const int jointCnt = model->mSkinInfo.mJointNames.size();
-						for ( int i=0; i<jointCnt; ++i, ++jointIt )
-						{
-							std::string lookingForJoint = (*jointIt).c_str();
-							//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
-							//and store it in the alternate bind matrix
-							if ( mJointList.find( lookingForJoint ) != mJointList.end() )
-							{
-								LLMatrix4 jointTransform = mJointList[lookingForJoint];
-								LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
-								newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
-								model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
-							}
-							else
-							{
-								LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL;
-							}
-						}
-						
-						//grab raw position array
-						
-						domVertices* verts = mesh->getVertices();
-						if (verts)
-						{
-							domInputLocal_Array& inputs = verts->getInput_array();
-							for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i)
-							{
-								if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0)
-								{
-									domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
-									if (pos_source)
-									{
-										domFloat_array* pos_array = pos_source->getFloat_array();
-										if (pos_array)
-										{
-											domListOfFloats& pos = pos_array->getValue();
-											
-											for (size_t j = 0; j < pos.getCount(); j += 3)
-											{
-												if (pos.getCount() <= j+2)
-												{
-													LL_ERRS() << "Invalid position array size." << LL_ENDL;
-												}
-												
-												LLVector3 v(pos[j], pos[j+1], pos[j+2]);
-												
-												//transform from COLLADA space to volume space
-												v = v * inverse_normalized_transformation;
-												
-												model->mPosition.push_back(v);
-											}
-										}
-									}
-								}
-							}
-						}
-						
-						//grab skin weights array
-						domSkin::domVertex_weights* weights = skin->getVertex_weights();
-						if (weights)
-						{
-							domInputLocalOffset_Array& inputs = weights->getInput_array();
-							domFloat_array* vertex_weights = NULL;
-							for (size_t i = 0; i < inputs.getCount(); ++i)
-							{
-								if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0)
-								{
-									domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
-									if (weight_source)
-									{
-										vertex_weights = weight_source->getFloat_array();
-									}
-								}
-							}
-							
-							if (vertex_weights)
-							{
-								domListOfFloats& w = vertex_weights->getValue();
-								domListOfUInts& vcount = weights->getVcount()->getValue();
-								domListOfInts& v = weights->getV()->getValue();
-								
-								U32 c_idx = 0;
-								for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx)
-								{ //for each vertex
-									daeUInt count = vcount[vc_idx];
-									
-									//create list of weights that influence this vertex
-									LLModel::weight_list weight_list;
-									
-									for (daeUInt i = 0; i < count; ++i)
-									{ //for each weight
-										daeInt joint_idx = v[c_idx++];
-										daeInt weight_idx = v[c_idx++];
-										
-										if (joint_idx == -1)
-										{
-											//ignore bindings to bind_shape_matrix
-											continue;
-										}
-										
-										F32 weight_value = w[weight_idx];
-										
-										weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value));
-									}
-									
-									//sort by joint weight
-									std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater());
-									
-									std::vector<LLModel::JointWeight> wght;
-									
-									F32 total = 0.f;
-									
-									for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i)
-									{ //take up to 4 most significant weights
-										if (weight_list[i].mWeight > 0.f)
-										{
-											wght.push_back( weight_list[i] );
-											total += weight_list[i].mWeight;
-										}
-									}
-									
-									F32 scale = 1.f/total;
-									if (scale != 1.f)
-									{ //normalize weights
-										for (U32 i = 0; i < wght.size(); ++i)
-										{
-											wght[i].mWeight *= scale;
-										}
-									}
-									
-									model->mSkinWeights[model->mPosition[vc_idx]] = wght;
-								}
-								
-								//add instance to scene for this model
-								
-								LLMatrix4 transformation = mTransform;
-								// adjust the transformation to compensate for mesh normalization
-								
-								LLMatrix4 mesh_translation;
-								mesh_translation.setTranslation(mesh_translation_vector);
-								mesh_translation *= transformation;
-								transformation = mesh_translation;
-								
-								LLMatrix4 mesh_scale;
-								mesh_scale.initScale(mesh_scale_vector);
-								mesh_scale *= transformation;
-								transformation = mesh_scale;
-								
-								std::map<std::string, LLImportMaterial> materials;
-								for (U32 i = 0; i < model->mMaterialList.size(); ++i)
-								{
-									materials[model->mMaterialList[i]] = LLImportMaterial();
-								}
-								mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
-								stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	daeElement* scene = root->getDescendant("visual_scene");
-	
-	if (!scene)
-	{
-		LL_WARNS() << "document has no visual_scene" << LL_ENDL;
-		setLoadState( ERROR_PARSING );
-		return true;
-	}
-	
-	setLoadState( DONE );
-
-	bool badElement = false;
-	
-	processElement( scene, badElement );
-	
-	if ( badElement )
-	{
-		setLoadState( ERROR_PARSING );
-	}
-	
-	return true;
-}
-
-void LLModelLoader::setLoadState(U32 state)
-{
-	if (mPreview)
-	{
-		mPreview->setLoadState(state);
-	}
-}
-
-bool LLModelLoader::loadFromSLM(const std::string& filename)
-{ 
-	//only need to populate mScene with data from slm
-	llstat stat;
-
-	if (LLFile::stat(filename, &stat))
-	{ //file does not exist
-		return false;
-	}
-
-	S32 file_size = (S32) stat.st_size;
-	
-	llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary);
-	LLSD data;
-	LLSDSerialize::fromBinary(data, ifstream, file_size);
-	ifstream.close();
-
-	//build model list for each LoD
-	model_list model[LLModel::NUM_LODS];
-
-	if (data["version"].asInteger() != SLM_SUPPORTED_VERSION)
-	{  //unsupported version
-		return false;
-	}
-
-	LLSD& mesh = data["mesh"];
-
-	LLVolumeParams volume_params;
-	volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
-
-	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
-	{
-		for (U32 i = 0; i < mesh.size(); ++i)
-		{
-			std::stringstream str(mesh[i].asString());
-			LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod);
-			if (loaded_model->loadModel(str))
-			{
-				loaded_model->mLocalID = i;
-				model[lod].push_back(loaded_model);
-
-				if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty())
-				{ 
-					//check to see if rig is valid					
-					mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );					
-				}
-			}
-		}
-	}	
-
-	if (model[LLModel::LOD_HIGH].empty())
-	{ //failed to load high lod
-		return false;
-	}
-
-	// Set name.
-	std::string name = data["name"];
-	if (!name.empty())
-	{
-		model[LLModel::LOD_HIGH][0]->mLabel = name;
-	}
-	
-
-	//load instance list
-	model_instance_list instance_list;
-
-	LLSD& instance = data["instance"];
-
-	for (U32 i = 0; i < instance.size(); ++i)
-	{
-		//deserialize instance list
-		instance_list.push_back(LLModelInstance(instance[i]));
-
-		//match up model instance pointers
-		S32 idx = instance_list[i].mLocalMeshID;
-
-		for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
-		{
-			if (!model[lod].empty())
-			{
-				instance_list[i].mLOD[lod] = model[lod][idx];
-			}
-		}
-
-		instance_list[i].mModel = model[LLModel::LOD_HIGH][idx];
-	}
-
-
-	//convert instance_list to mScene
-	mFirstTransform = TRUE;
-	for (U32 i = 0; i < instance_list.size(); ++i)
-	{
-		LLModelInstance& cur_instance = instance_list[i];
-		mScene[cur_instance.mTransform].push_back(cur_instance);
-		stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
-	}
-	
-	setLoadState( DONE );
-
-	return true;
-}
-
-//static
-bool LLModelLoader::isAlive(LLModelLoader* loader)
-{
-	if(!loader)
-	{
-		return false ;
-	}
-
-	std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ;
-	for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ;
-	
-	return *iter == loader ;
-}
-
-void LLModelLoader::loadModelCallback()
-{
-	assert_main_thread();
-
-	if (mPreview)
-	{
-		mPreview->loadModelCallback(mLod);	
-	}
-
-	while (!isStopped())
-	{ //wait until this thread is stopped before deleting self
-		apr_sleep(100);
-	}
-
-	//doubel check if "this" is valid before deleting it, in case it is aborted during running.
-	if(!isAlive(this))
-	{
-		return ;
-	}
-
-	//cleanup model loader
-	if (mPreview)
-	{
-		mPreview->mModelLoader = NULL;
-	}
-
-	delete this;
-}
-//-----------------------------------------------------------------------------
-// buildJointToNodeMappingFromScene()
-//-----------------------------------------------------------------------------
-void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot )
-{
-	daeElement* pScene = pRoot->getDescendant("visual_scene");
-	if ( pScene )
-	{
-		daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
-		S32 childCount = children.getCount();
-		for (S32 i = 0; i < childCount; ++i)
-		{
-			domNode* pNode = daeSafeCast<domNode>(children[i]);
-			processJointToNodeMapping( pNode );			
-		}
-	}
-}
-//-----------------------------------------------------------------------------
-// processJointToNodeMapping()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processJointToNodeMapping( domNode* pNode )
-{
-	if ( isNodeAJoint( pNode ) )
-	{
-		//1.Store the parent
-		std::string nodeName = pNode->getName();
-		if ( !nodeName.empty() )
-		{
-			mJointsFromNode.push_front( pNode->getName() );
-		}
-		//2. Handle the kiddo's
-		processChildJoints( pNode );
-	}
-	else
-	{
-		//Determine if the're any children wrt to this failed node.
-		//This occurs when an armature is exported and ends up being what essentially amounts to
-		//as the root for the visual_scene
-		if ( pNode ) 
-		{
-			processChildJoints( pNode );
-		}
-		else 
-		{
-			LL_INFOS()<<"Node is NULL"<<LL_ENDL;
-		}
-
-	}
-}
-//-----------------------------------------------------------------------------
-// processChildJoint()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processChildJoints( domNode* pParentNode )
-{	
-	daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren();
-	S32 childOfChildCount = childOfChild.getCount();
-	for (S32 i = 0; i < childOfChildCount; ++i)
-	{
-		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
-		if ( pChildNode )
-		{
-			processJointToNodeMapping( pChildNode );
-		}
-	}
-}
-
-//-----------------------------------------------------------------------------
-// critiqueRigForUploadApplicability()
-//-----------------------------------------------------------------------------
-void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
-{
-	critiqueJointToNodeMappingFromScene();
-	
-	//Determines the following use cases for a rig:
-	//1. It is suitable for upload with skin weights & joint positions, or
-	//2. It is suitable for upload as standard av with just skin weights
-	
-	bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
-	bool isRigLegacyOK			 = isRigLegacy( jointListFromAsset );
-
-	//It's OK that both could end up being true, both default to false
-	if ( isJointPositionUploadOK )
-	{
-		setRigValidForJointPositionUpload( true );
-	}
-
-	if ( isRigLegacyOK) 
-	{	
-		setLegacyRigValid( true );
-	}
-
-}
-//-----------------------------------------------------------------------------
-// critiqueJointToNodeMappingFromScene()
-//-----------------------------------------------------------------------------
-void LLModelPreview::critiqueJointToNodeMappingFromScene( void  )
-{
-	//Do the actual nodes back the joint listing from the dae?
-	//if yes then this is a fully rigged asset, otherwise it's just a partial rig
-	
-	std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin();
-	std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end();
-	bool result = true;
-
-	if ( !mJointsFromNode.empty() )
-	{
-		for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
-		{
-			std::string name = *jointsFromNodeIt;
-			if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
-			{
-				continue;
-			}
-			else
-			{
-				LL_INFOS()<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<LL_ENDL;
-				result = false;				
-			}
-		}
-	}
-	else
-	{
-		result = false;
-	}
-
-	//Determines the following use cases for a rig:
-	//1. Full av rig  w/1-1 mapping from the scene and joint array
-	//2. Partial rig but w/o parity between the scene and joint array
-	if ( result )
-	{		
-		setRigWithSceneParity( true );
-	}	
-}
-//-----------------------------------------------------------------------------
-// isRigLegacy()
-//-----------------------------------------------------------------------------
-bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
-{
-	//No joints in asset
-	if ( jointListFromAsset.size() == 0 )
-	{
-		return false;
-	}
-
-	bool result = false;
-
-	std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin();	
-	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
-	
-	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
-	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
-	
-	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
-	{
-		result = false;
-		modelJointIt = jointListFromAsset.begin();
-
-		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
-		{
-			if ( *masterJointIt == *modelJointIt )
-			{
-				result = true;
-				break;
-			}			
-		}		
-		if ( !result )
-		{
-			LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
-			break;
-		}
-	}	
-	return result;
-}
-//-----------------------------------------------------------------------------
-// isRigSuitableForJointPositionUpload()
-//-----------------------------------------------------------------------------
-bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
-{
-	bool result = false;
-
-	std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();	
-	std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end();
-	
-	std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();	
-	std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
-	
-	for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
-	{
-		result = false;
-		modelJointIt = jointListFromAsset.begin();
-
-		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
-		{
-			if ( *masterJointIt == *modelJointIt )
-			{
-				result = true;
-				break;
-			}			
-		}		
-		if ( !result )
-		{
-			LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
-			break;
-		}
-	}	
-	return result;
-}
-
-
-//called in the main thread
-void LLModelLoader::loadTextures()
-{
-	BOOL is_paused = isPaused() ;
-	pause() ; //pause the loader 
-
-	for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter)
-	{
-		for(U32 i = 0 ; i < iter->second.size(); i++)
-		{
-			for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin();
-				j != iter->second[i].mMaterial.end(); ++j)
-			{
-				LLImportMaterial& material = j->second;
-
-				if(!material.mDiffuseMapFilename.empty())
-				{
-					material.mDiffuseMap = 
-						LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
-					material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
-					material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
-					mNumOfFetchingTextures++ ;
-				}
-			}
-		}
-	}
-
-	if(!is_paused)
-	{
-		unpause() ;
-	}
-}
-
-//-----------------------------------------------------------------------------
-// isNodeAJoint()
-//-----------------------------------------------------------------------------
-bool LLModelLoader::isNodeAJoint( domNode* pNode )
-{
-	if ( !pNode )
-	{
-		LL_INFOS()<<"Created node is NULL"<<LL_ENDL;
-		return false;
-	}
-	
-	if ( pNode->getName() == NULL )
-	{
-		LL_INFOS()<<"Parsed node has no name "<<LL_ENDL;
-		//Attempt to write the node id, if possible (aids in debugging the visual scene)
-		if ( pNode->getId() )
-		{
-			LL_INFOS()<<"Parsed node ID: "<<pNode->getId()<<LL_ENDL;
-		}
-		return false;
-	}
-
-	if ( mJointMap.find( pNode->getName() )  != mJointMap.end() )
-	{
-		return true;
-	}
-
-	return false;
-}
-//-----------------------------------------------------------------------------
-// verifyCount
-//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyCount( int expected, int result )
-{
-	if ( expected != result )
-	{
-		LL_INFOS()<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<LL_ENDL;
-		return false;
-	}
-	return true;
-}
-//-----------------------------------------------------------------------------
-// verifyController
-//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyController( domController* pController )
-{	
-
-	bool result = true;
-
-	domSkin* pSkin = pController->getSkin();
-
-	if ( pSkin )
-	{
-		xsAnyURI & uri = pSkin->getSource();
-		domElement* pElement = uri.getElement();
-
-		if ( !pElement )
-		{
-			LL_INFOS()<<"Can't resolve skin source"<<LL_ENDL;
-			return false;
-		}
-
-		daeString type_str = pElement->getTypeName();
-		if ( stricmp(type_str, "geometry") == 0 )
-		{	
-			//Skin is reference directly by geometry and get the vertex count from skin
-			domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
-			U32 vertexWeightsCount = pVertexWeights->getCount();
-			domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
-			domMesh* pMesh = pGeometry->getMesh();				
-			
-			if ( pMesh )
-			{
-				//Get vertex count from geometry
-				domVertices* pVertices = pMesh->getVertices();
-				if ( !pVertices )
-				{ 
-					LL_INFOS()<<"No vertices!"<<LL_ENDL;
-					return false;
-				}
-
-				if ( pVertices )
-				{
-					xsAnyURI src = pVertices->getInput_array()[0]->getSource();
-					domSource* pSource = (domSource*) (domElement*) src.getElement();
-					U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
-					result = verifyCount( verticesCount, vertexWeightsCount );
-					if ( !result )
-					{
-						return result;
-					}
-				}
-			}	
-
-			U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
-			result = verifyCount( vcountCount, vertexWeightsCount );	
-			if ( !result )
-			{
-				return result;
-			}
-
-			domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
-			U32 sum = 0;
-			for (size_t i=0; i<vcountCount; i++)
-			{
-				sum += pVertexWeights->getVcount()->getValue()[i];
-			}
-			result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
-		}
-	}
-	
-	return result;
-}
-
-//-----------------------------------------------------------------------------
-// extractTranslation()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform )
-{
-	domFloat3 jointTrans = pTranslate->getValue();
-	LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
-	transform.setTranslation( singleJointTranslation );
-}
-//-----------------------------------------------------------------------------
-// extractTranslationViaElement()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
-{
-	if ( pTranslateElement )
-	{
-		domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
-		domFloat3 translateChild = pTranslateChild->getValue();
-		LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
-		transform.setTranslation( singleJointTranslation );
-	}	
-}
-//-----------------------------------------------------------------------------
-// extractTranslationViaSID()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform )
-{
-	if ( pElement )
-	{	
-		daeSIDResolver resolver( pElement, "./transform" );
-		domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() );
-		//We are only extracting out the translational component atm
-		LLMatrix4 workingTransform;
-		if ( pMatrix )
-		{
-			domFloat4x4 domArray = pMatrix->getValue();									
-			for ( int i = 0; i < 4; i++ )
-			{
-				for( int j = 0; j < 4; j++ )
-				{
-					workingTransform.mMatrix[i][j] = domArray[i + j*4];
-				}
-			}
-			LLVector3 trans = workingTransform.getTranslation();
-			transform.setTranslation( trans );	
-		}
-	}
-	else
-	{
-		LL_WARNS()<<"Element is nonexistent - empty/unsupported node."<<LL_ENDL;
-	}
-}
-//-----------------------------------------------------------------------------
-// processJointNode()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms )
-{
-	if (pNode->getName() == NULL)
-	{
-		LL_WARNS() << "nameless node, can't process" << LL_ENDL;
-		return;
-	}
-
-	//LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL;
-
-	//1. handle the incoming node - extract out translation via SID or element
-
-	LLMatrix4 workingTransform;
-
-	//Pull out the translate id and store it in the jointTranslations map
-	daeSIDResolver jointResolverA( pNode, "./translate" );
-	domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
-	daeSIDResolver jointResolverB( pNode, "./location" );
-	domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
-
-	//Translation via SID was successful
-	if ( pTranslateA )
-	{
-		extractTranslation( pTranslateA, workingTransform );
-	}
-	else
-	if ( pTranslateB )
-	{
-		extractTranslation( pTranslateB, workingTransform );
-	}
-	else
-	{
-		//Translation via child from element
-		daeElement* pTranslateElement = getChildFromElement( pNode, "translate" );
-		if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() )
-		{
-			//LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
-			daeSIDResolver jointResolver( pNode, "./matrix" );
-			domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() );
-			if ( pMatrix )
-			{
-				//LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL;
-				domFloat4x4 domArray = pMatrix->getValue();									
-				for ( int i = 0; i < 4; i++ )
-				{
-					for( int j = 0; j < 4; j++ )
-					{
-						workingTransform.mMatrix[i][j] = domArray[i + j*4];
-					}
-				}
-			}
-			else
-			{
-				LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL;
-			}
-		}
-		else
-		{
-			extractTranslationViaElement( pTranslateElement, workingTransform );
-		}
-	}
-
-	//Store the working transform relative to the nodes name.
-	jointTransforms[ pNode->getName() ] = workingTransform;
-
-	//2. handle the nodes children
-
-	//Gather and handle the incoming nodes children
-	daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
-	S32 childOfChildCount = childOfChild.getCount();
-
-	for (S32 i = 0; i < childOfChildCount; ++i)
-	{
-		domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
-		if ( pChildNode )
-		{
-			processJointNode( pChildNode, jointTransforms );
-		}
-	}
-}
-//-----------------------------------------------------------------------------
-// getChildFromElement()
-//-----------------------------------------------------------------------------
-daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name )
-{
-    daeElement* pChildOfElement = pElement->getChild( name.c_str() );
-	if ( pChildOfElement )
-	{
-		return pChildOfElement;
-	}
-	LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
-    return NULL;
-}
-
-void LLModelLoader::processElement( daeElement* element, bool& badElement )
-{
-	LLMatrix4 saved_transform = mTransform;
-
-	domTranslate* translate = daeSafeCast<domTranslate>(element);
-	if (translate)
-	{
-		domFloat3 dom_value = translate->getValue();
-
-		LLMatrix4 translation;
-		translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2]));
-
-		translation *= mTransform;
-		mTransform = translation;
-	}
-
-	domRotate* rotate = daeSafeCast<domRotate>(element);
-	if (rotate)
-	{
-		domFloat4 dom_value = rotate->getValue();
-
-		LLMatrix4 rotation;
-		rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0));
-
-		rotation *= mTransform;
-		mTransform = rotation;
-	}
-
-	domScale* scale = daeSafeCast<domScale>(element);
-	if (scale)
-	{
-		domFloat3 dom_value = scale->getValue();
-
-
-		LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]);
-		scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes
-		LLMatrix4 scaling;
-		scaling.initScale(scale_vector);
-
-		scaling *= mTransform;
-		mTransform = scaling;
-	}
-
-	domMatrix* matrix = daeSafeCast<domMatrix>(element);
-	if (matrix)
-	{
-		domFloat4x4 dom_value = matrix->getValue();
-
-		LLMatrix4 matrix_transform;
-
-		for (int i = 0; i < 4; i++)
-		{
-			for(int j = 0; j < 4; j++)
-			{
-				matrix_transform.mMatrix[i][j] = dom_value[i + j*4];
-			}
-		}
-
-		matrix_transform *= mTransform;
-		mTransform = matrix_transform;
-	}
-
-	domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element);
-	if (instance_geo)
-	{
-		domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement());
-		if (geo)
-		{
-			domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())));
-			if (mesh)
-			{
-				LLModel* model = mModel[mesh];
-				if (model)
-				{
-					LLMatrix4 transformation = mTransform;
-
-					if (mTransform.determinant() < 0)
-					{ //negative scales are not supported
-						LL_INFOS() << "Negative scale detected, unsupported transform.  domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << LL_ENDL;
-						badElement = true;
-					}
-					
-					std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo);
-
-					// adjust the transformation to compensate for mesh normalization
-					LLVector3 mesh_scale_vector;
-					LLVector3 mesh_translation_vector;
-					model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-
-					LLMatrix4 mesh_translation;
-					mesh_translation.setTranslation(mesh_translation_vector);
-					mesh_translation *= transformation;
-					transformation = mesh_translation;
-
-					LLMatrix4 mesh_scale;
-					mesh_scale.initScale(mesh_scale_vector);
-					mesh_scale *= transformation;
-					transformation = mesh_scale;
-
-					std::string label = getElementLabel(instance_geo);
-					mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
-
-					stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
-				}
-			}
-		}
-		else 
-		{
-			LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL;
-			badElement = true;			
-		}
-
-	}
-
-	domInstance_node* instance_node = daeSafeCast<domInstance_node>(element);
-	if (instance_node)
-	{
-		daeElement* instance = instance_node->getUrl().getElement();
-		if (instance)
-		{
-			processElement(instance,badElement);
-		}
-	}
-
-	//process children
-	daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
-	int childCount = children.getCount();
-	for (S32 i = 0; i < childCount; i++)
-	{
-		processElement(children[i],badElement);
-	}
-
-	domNode* node = daeSafeCast<domNode>(element);
-	if (node)
-	{ //this element was a node, restore transform before processiing siblings
-		mTransform = saved_transform;
-	}
-}
-
-std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo)
-{
-	std::map<std::string, LLImportMaterial> materials;
-	for (int i = 0; i < model->mMaterialList.size(); i++)
-	{
-		LLImportMaterial import_material;
-
-		domInstance_material* instance_mat = NULL;
-
-		domBind_material::domTechnique_common* technique =
-		daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID())));
-
-		if (technique)
-		{
-			daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>();
-			for (int j = 0; j < inst_materials.getCount(); j++)
-			{
-				std::string symbol(inst_materials[j]->getSymbol());
-
-				if (symbol == model->mMaterialList[i]) // found the binding
-				{
-					instance_mat = inst_materials[j];
-				}
-			}
-		}
-
-		if (instance_mat)
-		{
-			domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement());
-			if (material)
-			{
-				domInstance_effect* instance_effect =
-				daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID())));
-				if (instance_effect)
-				{
-					domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement());
-					if (effect)
-					{
-						domProfile_COMMON* profile =
-						daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID())));
-						if (profile)
-						{
-							import_material = profileToMaterial(profile);
-						}
-					}
-				}
-			}
-		}
-
-		import_material.mBinding = model->mMaterialList[i];
-		materials[model->mMaterialList[i]] = import_material;
-	}
-
-	return materials;
-}
-
-LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material)
-{
-	LLImportMaterial mat;
-	mat.mFullbright = FALSE;
-
-	daeElement* diffuse = material->getDescendant("diffuse");
-	if (diffuse)
-	{
-		domCommon_color_or_texture_type_complexType::domTexture* texture =
-		daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture"));
-		if (texture)
-		{
-			domCommon_newparam_type_Array newparams = material->getNewparam_array();
-			for (S32 i = 0; i < newparams.getCount(); i++)
-			{
-				domFx_surface_common* surface = newparams[i]->getSurface();
-				if (surface)
-				{
-					domFx_surface_init_common* init = surface->getFx_surface_init_common();
-					if (init)
-					{
-						domFx_surface_init_from_common_Array init_from = init->getInit_from_array();
-
-						if (init_from.getCount() > i)
-						{
-							domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement());
-							if (image)
-							{
-								// we only support init_from now - embedded data will come later
-								domImage::domInit_from* init = image->getInit_from();
-								if (init)
-								{									
-									mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str());
-									mat.mDiffuseMapLabel = getElementLabel(material);
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		domCommon_color_or_texture_type_complexType::domColor* color =
-		daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color"));
-		if (color)
-		{
-			domFx_color_common domfx_color = color->getValue();
-			LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
-			mat.mDiffuseColor = value;
-		}
-	}
-
-	daeElement* emission = material->getDescendant("emission");
-	if (emission)
-	{
-		LLColor4 emission_color = getDaeColor(emission);
-		if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25)
-		{
-			mat.mFullbright = TRUE;
-		}
-	}
-
-	return mat;
-}
-
-// try to get a decent label for this element
-std::string LLModelLoader::getElementLabel(daeElement *element)
-{
-	// if we have a name attribute, use it
-	std::string name = element->getAttribute("name");
-	if (name.length())
-	{
-		return name;
-	}
-
-	// if we have an ID attribute, use it
-	if (element->getID())
-	{
-		return std::string(element->getID());
-	}
-
-	// if we have a parent, use it
-	daeElement* parent = element->getParent();
-	if (parent)
-	{
-		// if parent has a name, use it
-		std::string name = parent->getAttribute("name");
-		if (name.length())
-		{
-			return name;
-		}
-
-		// if parent has an ID, use it
-		if (parent->getID())
-		{
-			return std::string(parent->getID());
-		}
-	}
-
-	// try to use our type
-	daeString element_name = element->getElementName();
-	if (element_name)
-	{
-		return std::string(element_name);
-	}
-
-	// if all else fails, use "object"
-	return std::string("object");
-}
-
-LLColor4 LLModelLoader::getDaeColor(daeElement* element)
-{
-	LLColor4 value;
-	domCommon_color_or_texture_type_complexType::domColor* color =
-	daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color"));
-	if (color)
-	{
-		domFx_color_common domfx_color = color->getValue();
-		value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
-	}
-
-	return value;
-}
-
-//-----------------------------------------------------------------------------
-// LLModelPreview
-//-----------------------------------------------------------------------------
-
-LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
-: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
-, mPelvisZOffset( 0.0f )
-, mLegacyRigValid( false )
-, mRigValidJointUpload( false )
-, mResetJoints( false )
-, mRigParityWithScene( false )
-, mLastJointUpdate( false )
-{
-	mNeedsUpdate = TRUE;
-	mCameraDistance = 0.f;
-	mCameraYaw = 0.f;
-	mCameraPitch = 0.f;
-	mCameraZoom = 1.f;
-	mTextureName = 0;
-	mPreviewLOD = 0;
-	mModelLoader = NULL;
-	mMaxTriangleLimit = 0;
-	mDirty = false;
-	mGenLOD = false;
-	mLoading = false;
-	mLoadState = LLModelLoader::STARTING;
-	mGroup = 0;
-	mLODFrozen = false;
-	mBuildShareTolerance = 0.f;
-	mBuildQueueMode = GLOD_QUEUE_GREEDY;
-	mBuildBorderMode = GLOD_BORDER_UNLOCK;
-	mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE;
-
-	for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
-	{
-		mRequestedTriangleCount[i] = 0;
-		mRequestedCreaseAngle[i] = -1.f;
-		mRequestedLoDMode[i] = 0;
-		mRequestedErrorThreshold[i] = 0.f;
-		mRequestedBuildOperator[i] = 0;
-		mRequestedQueueMode[i] = 0;
-		mRequestedBorderMode[i] = 0;
-		mRequestedShareTolerance[i] = 0.f;
-	}
-
-	mViewOption["show_textures"] = false;
-
-	mFMP = fmp;
-
-	mHasPivot = false;
-	mModelPivot = LLVector3( 0.0f, 0.0f, 0.0f );
-	
-	glodInit();
-
-	//move into joint mapper class
-	//1. joints for joint offset verification
-	mMasterJointList.push_front("mPelvis");
-	mMasterJointList.push_front("mTorso");
-	mMasterJointList.push_front("mChest");
-	mMasterJointList.push_front("mNeck");
-	mMasterJointList.push_front("mHead");
-	mMasterJointList.push_front("mCollarLeft");
-	mMasterJointList.push_front("mShoulderLeft");
-	mMasterJointList.push_front("mElbowLeft");
-	mMasterJointList.push_front("mWristLeft");
-	mMasterJointList.push_front("mCollarRight");
-	mMasterJointList.push_front("mShoulderRight");
-	mMasterJointList.push_front("mElbowRight");
-	mMasterJointList.push_front("mWristRight");
-	mMasterJointList.push_front("mHipRight");
-	mMasterJointList.push_front("mKneeRight");
-	mMasterJointList.push_front("mFootRight");
-	mMasterJointList.push_front("mHipLeft");
-	mMasterJointList.push_front("mKneeLeft");
-	mMasterJointList.push_front("mFootLeft");
-	//2. legacy joint list - used to verify rigs that will not be using joint offsets
-	mMasterLegacyJointList.push_front("mPelvis");
-	mMasterLegacyJointList.push_front("mTorso");
-	mMasterLegacyJointList.push_front("mChest");
-	mMasterLegacyJointList.push_front("mNeck");
-	mMasterLegacyJointList.push_front("mHead");
-	mMasterLegacyJointList.push_front("mHipRight");
-	mMasterLegacyJointList.push_front("mKneeRight");
-	mMasterLegacyJointList.push_front("mFootRight");
-	mMasterLegacyJointList.push_front("mHipLeft");
-	mMasterLegacyJointList.push_front("mKneeLeft");
-	mMasterLegacyJointList.push_front("mFootLeft");
-
-	createPreviewAvatar();
-}
-
-LLModelPreview::~LLModelPreview()
-{
-	if (mModelLoader)
-	{
-		mModelLoader->mPreview = NULL;
-		mModelLoader = NULL;
-	}
-	//*HACK : *TODO : turn this back on when we understand why this crashes
-	//glodShutdown();
-}
-
-U32 LLModelPreview::calcResourceCost()
-{
-	assert_main_thread();
-
-	rebuildUploadData();
-
-	//Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
-	if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
-	{
-		bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
-		if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
-		{
-			mFMP->childDisable("ok_btn");		
-		}		
-	}
-	
-	std::set<LLModel*> accounted;
-	U32 num_points = 0;
-	U32 num_hulls = 0;
-
-	F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f;
-	mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f;
-	
-	if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() )
-	{
-		// FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail.
-		// see also call to addAttachmentPosOverride.
-		LLUUID fake_mesh_id;
-		fake_mesh_id.generate();
-		getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id );
-	}
-
-	F32 streaming_cost = 0.f;
-	F32 physics_cost = 0.f;
-	for (U32 i = 0; i < mUploadData.size(); ++i)
-	{
-		LLModelInstance& instance = mUploadData[i];
-		
-		if (accounted.find(instance.mModel) == accounted.end())
-		{
-			accounted.insert(instance.mModel);
-
-			LLModel::Decomposition& decomp =
-			instance.mLOD[LLModel::LOD_PHYSICS] ?
-			instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
-			instance.mModel->mPhysics;
-			
-			//update instance skin info for each lods pelvisZoffset 
-			for ( int j=0; j<LLModel::NUM_LODS; ++j )
-			{	
-				if ( instance.mLOD[j] )
-				{
-					instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;
-				}
-			}
-
-			std::stringstream ostr;
-			LLSD ret = LLModel::writeModel(ostr,
-					   instance.mLOD[4],
-					   instance.mLOD[3],
-					   instance.mLOD[2],
-					   instance.mLOD[1],
-					   instance.mLOD[0],
-					   decomp,
-					   mFMP->childGetValue("upload_skin").asBoolean(),
-					   mFMP->childGetValue("upload_joints").asBoolean(),
-					   TRUE);
-			
-			num_hulls += decomp.mHull.size();
-			for (U32 i = 0; i < decomp.mHull.size(); ++i)
-			{
-				num_points += decomp.mHull[i].size();
-			}
-
-			//calculate streaming cost
-			LLMatrix4 transformation = instance.mTransform;
-
-			LLVector3 position = LLVector3(0, 0, 0) * transformation;
-
-			LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
-			LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
-			LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
-			F32 x_length = x_transformed.normalize();
-			F32 y_length = y_transformed.normalize();
-			F32 z_length = z_transformed.normalize();
-			LLVector3 scale = LLVector3(x_length, y_length, z_length);
-
-			F32 radius = scale.length()*0.5f*debug_scale;
-
-			streaming_cost += LLMeshRepository::getStreamingCost(ret, radius);
-		}
-	}
-
-	F32 scale = mFMP ? mFMP->childGetValue("import_scale").asReal()*2.f : 2.f;
-
-	mDetailsSignal(mPreviewScale[0]*scale, mPreviewScale[1]*scale, mPreviewScale[2]*scale, streaming_cost, physics_cost);
-
-	updateStatusMessages();
-
-	return (U32) streaming_cost;
-}
-
-void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
-{
-	assert_main_thread();
-	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
-	childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
-	childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
-}
-
-
-void LLModelPreview::rebuildUploadData()
-{
-	assert_main_thread();
-
-	mUploadData.clear();
-	mTextureSet.clear();
+	mUploadData.clear();
+	mTextureSet.clear();
 
 	//fill uploaddata instance vectors from scene data
 
@@ -3351,29 +1380,12 @@ void LLModelPreview::rebuildUploadData()
 
 	F32 max_scale = 0.f;
 
-	//reorder materials to match mBaseModel
-	for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
-	{
-		if (mBaseModel.size() == mModel[i].size())
-		{
-			for (U32 j = 0; j < mBaseModel.size(); ++j)
-			{
-				
-				int refFaceCnt = 0;
-				int modelFaceCnt = 0;
-				
-				if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
-				{
-					setLoadState( LLModelLoader::ERROR_MATERIALS );
-					mFMP->childDisable( "calculate_btn" );
-				}
-			}
-		}
-	}
+	BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+	BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
 
 	for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
 	{ //for each transform in scene
-		LLMatrix4 mat = iter->first;
+		LLMatrix4 mat		= iter->first;
 
 		// compute position
 		LLVector3 position = LLVector3(0, 0, 0) * mat;
@@ -3390,43 +1402,204 @@ void LLModelPreview::rebuildUploadData()
 
 		mat *= scale_mat;
 
-		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
-		{ //for each instance with said transform applied
-			LLModelInstance instance = *model_iter;
+		for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
+		{ //for each instance with said transform applied 
+			LLModelInstance instance = *model_iter++;
 
 			LLModel* base_model = instance.mModel;
 			
-			if (base_model)
+			if (base_model && !requested_name.empty())
 			{
 				base_model->mRequestedLabel = requested_name;
 				base_model->mMetric = metric;
 			}
 
-			S32 idx = 0;
-			for (idx = 0; idx < mBaseModel.size(); ++idx)
-			{  //find reference instance for this model
-				if (mBaseModel[idx] == base_model)
+			for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--)
+			{
+				LLModel* lod_model = NULL;
+				if (!legacyMatching)
+				{
+					// Fill LOD slots by finding matching meshes by label with name extensions
+					// in the appropriate scene for each LOD. This fixes all kinds of issues
+					// where the indexed method below fails in spectacular fashion.
+					// If you don't take the time to name your LOD and PHYS meshes
+					// with the name of their corresponding mesh in the HIGH LOD,
+					// then the indexed method will be attempted below.
+
+					LLMatrix4 transform;
+
+					std::string name_to_match = instance.mLabel;
+					llassert(!name_to_match.empty());
+
+					int extensionLOD;
+					if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty())
+					{
+						extensionLOD = i;
+					}
+					else
+					{
+						//Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
+						extensionLOD = mPhysicsSearchLOD;
+					}
+
+					std::string toAdd;
+					switch (extensionLOD)
+					{
+					case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
+					case LLModel::LOD_LOW:      toAdd = "_LOD1"; break;
+					case LLModel::LOD_MEDIUM:   toAdd = "_LOD2"; break;
+					case LLModel::LOD_PHYSICS:  toAdd = "_PHYS"; break;
+					case LLModel::LOD_HIGH:                      break;
+					}
+
+					if (name_to_match.find(toAdd) == -1)
+					{
+						name_to_match += toAdd;
+					}
+
+					FindModel(mScene[i], name_to_match, lod_model, transform);
+
+					if (!lod_model && i != LLModel::LOD_PHYSICS)
+					{
+						if (importerDebug)
+						{
+							LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL;
+						}
+
+						int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
+						while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
+						{
+							std::string name_to_match = instance.mLabel;
+							llassert(!name_to_match.empty());
+
+							std::string toAdd;
+							switch (searchLOD)
+							{
+							case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
+							case LLModel::LOD_LOW:      toAdd = "_LOD1"; break;
+							case LLModel::LOD_MEDIUM:   toAdd = "_LOD2"; break;
+							case LLModel::LOD_PHYSICS:  toAdd = "_PHYS"; break;
+							case LLModel::LOD_HIGH:                      break;
+							}
+
+							if (name_to_match.find(toAdd) == -1)
+							{
+								name_to_match += toAdd;
+							}
+
+							// See if we can find an appropriately named model in LOD 'searchLOD'
+							//
+							FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
+							searchLOD++;
+						}
+					}
+				}
+				else
+				{
+					// Use old method of index-based association
+					U32 idx = 0;
+					for (idx = 0; idx < mBaseModel.size(); ++idx)
+					{
+						// find reference instance for this model
+						if (mBaseModel[idx] == base_model)
+						{
+							if (importerDebug)
+							{
+								LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL;
+							}
+							break;
+						}
+					}
+
+					// If the model list for the current LOD includes that index...
+					//
+					if (mModel[i].size() > idx)
+					{
+						// Assign that index from the model list for our LOD as the LOD model for this instance
+						//
+						lod_model = mModel[i][idx];
+						if (importerDebug)
+						{
+							LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL;
+						}
+					}
+					else if (importerDebug)
+					{
+						LL_INFOS() << "List of models does not include index " << idx << LL_ENDL;
+					}
+				}
+
+				if (lod_model)
+				{
+					if (importerDebug)
+					{
+						if (i == LLModel::LOD_PHYSICS)
+						{
+							LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL;
+						}
+						else
+						{
+							LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL;
+						}
+					}
+					instance.mLOD[i] = lod_model;
+				}
+				else if (importerDebug)
+				{
+					LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL;
+				}
+			}
+
+			LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH];
+			if (!high_lod_model)
+			{
+				setLoadState( LLModelLoader::ERROR_MATERIALS );
+				mFMP->childDisable( "calculate_btn" );
+			}
+			else
+			{
+				for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+				{				
+					int refFaceCnt = 0;
+					int modelFaceCnt = 0;
+					llassert(instance.mLOD[i]);
+					if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) )
+					{
+						setLoadState( LLModelLoader::ERROR_MATERIALS );
+						mFMP->childDisable( "calculate_btn" );
+					}
+				}
+			}
+			instance.mTransform = mat;
+			mUploadData.push_back(instance);
+		}
+	}
+
+	for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++)
+	{
+		// Search for models that are not included into upload data
+		// If we found any, that means something we loaded is not a sub-model.
+		for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind)
+		{
+			bool found_model = false;
+			for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+			{
+				LLModelInstance& instance = *iter;
+				if (instance.mLOD[lod] == mModel[lod][model_ind])
 				{
+					found_model = true;
 					break;
 				}
 			}
-
-			if(idx < mBaseModel.size())
+			if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID)
 			{
-				for (U32 i = 0; i < LLModel::NUM_LODS; i++)
-				{ //fill LOD slots based on reference model index
-					if (mModel[i].size() > idx)
-					{
-						instance.mLOD[i] = mModel[i][idx];
-					}
-					else
-					{
-						instance.mLOD[i] = NULL;
-					}
+				if (importerDebug)
+				{
+					LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." <<  LL_ENDL;
 				}
+				setLoadState( LLModelLoader::ERROR_MATERIALS );
+				mFMP->childDisable( "calculate_btn" );
 			}
-			instance.mTransform = mat;
-			mUploadData.push_back(instance);
 		}
 	}
 
@@ -3496,7 +1669,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
 			meshes.insert(instance.mModel);
 
 			std::stringstream str;
-
 			LLModel::Decomposition& decomp =
 				instance.mLOD[LLModel::LOD_PHYSICS].notNull() ? 
 				instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics : 
@@ -3509,8 +1681,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
 				instance.mLOD[LLModel::LOD_LOW], 
 				instance.mLOD[LLModel::LOD_IMPOSTOR], 
 				decomp, 
-				save_skinweights, save_joint_positions, FALSE, TRUE);
-
+				save_skinweights, save_joint_positions,
+                FALSE, TRUE, instance.mModel->mSubmodelID);
 			
 			data["mesh"][instance.mModel->mLocalID] = str.str();
 		}
@@ -3578,13 +1750,28 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
 		clearGLODGroup();
 	}
 
-	mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode );
+	mModelLoader = new LLDAELoader(
+		filename,
+		lod, 
+		&LLModelPreview::loadedCallback,
+		&LLModelPreview::lookupJointByName,
+		&LLModelPreview::loadTextures,
+		&LLModelPreview::stateChangedCallback,
+		this,
+		mJointTransformMap,
+		mJointsFromNode,
+		gSavedSettings.getU32("ImporterModelLimit"));
 
 	if (force_disable_slm)
 	{
 		mModelLoader->mTrySLM = false;
 	}
-
+	else
+	{
+		//only try to load from slm if viewer is configured to do so and this is the 
+		//initial model load (not an LoD or physics shape)
+		mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
+	}
 	mModelLoader->start();
 
 	mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file"));
@@ -3615,6 +1802,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod)
 
 	if (lod >= 0 && lod <= 3)
 	{
+		mPhysicsSearchLOD = lod;
 		mModel[LLModel::LOD_PHYSICS] = mModel[lod];
 		mScene[LLModel::LOD_PHYSICS] = mScene[lod];
 		mLODFile[LLModel::LOD_PHYSICS].clear();
@@ -3634,11 +1822,14 @@ void LLModelPreview::clearIncompatible(S32 lod)
 		return;
 	}
 
+	// at this point we don't care about sub-models,
+	// different amount of sub-models means face count mismatch, not incompatibility
+	U32 lod_size = countRootModels(mModel[lod]);
 	for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
 	{ //clear out any entries that aren't compatible with this model
 		if (i != lod)
 		{
-			if (mModel[i].size() != mModel[lod].size())
+			if (countRootModels(mModel[i]) != lod_size)
 			{
 				mModel[i].clear();
 				mScene[i].clear();
@@ -3673,7 +1864,7 @@ void LLModelPreview::clearGLODGroup()
 	}
 }
 
-void LLModelPreview::loadModelCallback(S32 lod)
+void LLModelPreview::loadModelCallback(S32 loaded_lod)
 {
 	assert_main_thread();
 
@@ -3686,12 +1877,18 @@ void LLModelPreview::loadModelCallback(S32 lod)
 	if(getLoadState() >= LLModelLoader::ERROR_PARSING)
 	{
 		mLoading = false ;
+		mModelLoader = NULL;
 		return ;
 	}
 
+	// Copy determinations about rig so UI will reflect them
+	//
+	setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
+	setLegacyRigValid(mModelLoader->isLegacyRigValid());
+
 	mModelLoader->loadTextures() ;
 
-	if (lod == -1)
+	if (loaded_lod == -1)
 	{ //populate all LoDs from model loader scene
 		mBaseModel.clear();
 		mBaseScene.clear();
@@ -3723,6 +1920,11 @@ void LLModelPreview::loadModelCallback(S32 lod)
 						//override displayed model with current LoD
 						list_iter->mModel = list_iter->mLOD[lod];
 
+						if (!list_iter->mModel)
+						{
+							continue;
+						}
+
 						//add current model to current LoD's model list (LLModel::mLocalID makes a good vector index)
 						S32 idx = list_iter->mModel->mLocalID;
 
@@ -3731,7 +1933,7 @@ void LLModelPreview::loadModelCallback(S32 lod)
 							mModel[lod].resize(idx+1);
 						}
 
-						mModel[lod][idx] = list_iter->mModel;	
+						mModel[lod][idx] = list_iter->mModel;
 						if (!list_iter->mModel->mSkinWeights.empty())
 						{
 							skin_weights = true;
@@ -3774,31 +1976,108 @@ void LLModelPreview::loadModelCallback(S32 lod)
 	}
 	else
 	{ //only replace given LoD
-		mModel[lod] = mModelLoader->mModelList;
-		mScene[lod] = mModelLoader->mScene;
-		mVertexBuffer[lod].clear();
+		mModel[loaded_lod] = mModelLoader->mModelList;
+		mScene[loaded_lod] = mModelLoader->mScene;
+		mVertexBuffer[loaded_lod].clear();
 
-		setPreviewLOD(lod);
+		setPreviewLOD(loaded_lod);
 
-		if (lod == LLModel::LOD_HIGH)
+		if (loaded_lod == LLModel::LOD_HIGH)
 		{ //save a copy of the highest LOD for automatic LOD manipulation
 			if (mBaseModel.empty())
 			{ //first time we've loaded a model, auto-gen LoD
 				mGenLOD = true;
 			}
 
-			mBaseModel = mModel[lod];
+			mBaseModel = mModel[loaded_lod];
 			clearGLODGroup();
 
-			mBaseScene = mScene[lod];
+			mBaseScene = mScene[loaded_lod];
 			mVertexBuffer[5].clear();
 		}
+		else
+		{
+			BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+			BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
+			if (!legacyMatching)
+			{
+				if (!mBaseModel.empty())
+				{ 
+					BOOL name_based = FALSE;
+					BOOL has_submodels = FALSE;
+					for (U32 idx = 0; idx < mBaseModel.size(); ++idx)
+					{
+						if (mBaseModel[idx]->mSubmodelID)
+						{ // don't do index-based renaming when the base model has submodels
+							has_submodels = TRUE;
+							if (importerDebug)
+							{
+								LL_INFOS() << "High LOD has submodels" << LL_ENDL;
+							}
+							break;
+						}
+					}
+
+					for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx)
+					{
+						std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+						LLModel* found_model = NULL;
+						LLMatrix4 transform;
+						FindModel(mBaseScene, loaded_name, found_model, transform);
+						if (found_model)
+						{ // don't rename correctly named models (even if they are placed in a wrong order)
+							name_based = TRUE;
+						}
+
+						if (mModel[loaded_lod][idx]->mSubmodelID)
+						{ // don't rename the models when loaded LOD model has submodels
+							has_submodels = TRUE;
+						}
+					}
+
+					if (importerDebug)
+					{
+						LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL;
+					}
+
+					if (!name_based && !has_submodels)
+					{ // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601)
+					  // this actually works like "ImporterLegacyMatching" for this particular LOD
+						for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx)
+						{ 
+							std::string name = mBaseModel[idx]->mLabel;
+							std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+							if (loaded_name != name)
+							{
+								switch (loaded_lod)
+								{
+								case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
+								case LLModel::LOD_LOW:      name += "_LOD1"; break;
+								case LLModel::LOD_MEDIUM:   name += "_LOD2"; break;
+								case LLModel::LOD_PHYSICS:  name += "_PHYS"; break;
+								case LLModel::LOD_HIGH:                      break;
+								}
+
+								if (importerDebug)
+								{
+									LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL;
+								}
+
+								mModel[loaded_lod][idx]->mLabel = name;
+							}
+						}
+					}
+				}
+			}
+		}
 
-		clearIncompatible(lod);
+		clearIncompatible(loaded_lod);
 
 		mDirty = true;
 
-		if (lod == LLModel::LOD_HIGH)
+		if (loaded_lod == LLModel::LOD_HIGH)
 		{
 			resetPreviewTarget();
 		}
@@ -3817,6 +2096,8 @@ void LLModelPreview::loadModelCallback(S32 lod)
 	refresh();
 
 	mModelLoadedSignal();
+
+	mModelLoader = NULL;
 }
 
 void LLModelPreview::resetPreviewTarget()
@@ -4165,6 +2446,20 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
 			volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
 			mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
 
+            std::string name = base->mLabel;
+
+            switch (lod)
+            {
+                case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
+                case LLModel::LOD_LOW:      name += "_LOD1"; break;
+		        case LLModel::LOD_MEDIUM:   name += "_LOD2"; break;
+                case LLModel::LOD_PHYSICS:  name += "_PHYS"; break;
+                case LLModel::LOD_HIGH:                      break;
+            }
+
+            mModel[lod][mdl_idx]->mLabel = name;
+			mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
+            
 			GLint* sizes = new GLint[patch_count*2];
 			glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
 			stop_gloderror();
@@ -4277,17 +2572,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
 	{
 		shader->bind();
 	}
-
-	/*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty())
-	 { //build physics scene
-	 mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW];
-	 mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW];
-
-	 for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
-	 {
-	 mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]);
-	 }
-	 }*/
 }
 
 void LLModelPreview::updateStatusMessages()
@@ -4304,43 +2588,89 @@ void LLModelPreview::updateStatusMessages()
 	S32 total_verts[LLModel::NUM_LODS];
 	S32 total_submeshes[LLModel::NUM_LODS];
 
-	for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
+    for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+    {
+        total_tris[i] = 0;
+	    total_verts[i] = 0;
+	    total_submeshes[i] = 0;
+    }
+
+    for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
 	{
-		//initialize total for this lod to 0
-		total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0;
+		LLModelInstance& instance = *iter;
 
-		for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter)
+        LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH];
+        if (!model_high_lod)
 		{
-			for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
-			{
-				LLModel* model = instance->mModel;
-				if (model)
-				{
-					 //for each model in the lod
-					S32 cur_tris = 0;
-					S32 cur_verts = 0;
-					S32 cur_submeshes = model->getNumVolumeFaces();
+			setLoadState( LLModelLoader::ERROR_MATERIALS );
+			mFMP->childDisable( "calculate_btn" );
+			continue;
+		}
 
-					for (S32 j = 0; j < cur_submeshes; ++j)
-					{ //for each submesh (face), add triangles and vertices to current total
-						const LLVolumeFace& face = model->getVolumeFace(j);
-						cur_tris += face.mNumIndices/3;
-						cur_verts += face.mNumVertices;
-					}
+        for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+		{
+            LLModel* lod_model = instance.mLOD[i];
+            if (!lod_model)
+            {
+                setLoadState( LLModelLoader::ERROR_MATERIALS );
+                mFMP->childDisable( "calculate_btn" );
+            }
+
+            int refFaceCnt = 0;
+            int modelFaceCnt = 0;
+
+            if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) )
+			{
+                setLoadState( LLModelLoader::ERROR_MATERIALS );
+				mFMP->childDisable( "calculate_btn" );
+			}
 
-					//add this model to the lod total
-					total_tris[lod] += cur_tris;
-					total_verts[lod] += cur_verts;
-					total_submeshes[lod] += cur_submeshes;
+            if (lod_model)
+			{
+					//for each model in the lod
+				S32 cur_tris = 0;
+				S32 cur_verts = 0;
+				S32 cur_submeshes = lod_model->getNumVolumeFaces();
 
-					//store this model's counts to asset data
-					tris[lod].push_back(cur_tris);
-					verts[lod].push_back(cur_verts);
-					submeshes[lod].push_back(cur_submeshes);
+				for (S32 j = 0; j < cur_submeshes; ++j)
+				{ //for each submesh (face), add triangles and vertices to current total
+					const LLVolumeFace& face = lod_model->getVolumeFace(j);
+					cur_tris += face.mNumIndices/3;
+					cur_verts += face.mNumVertices;
 				}
+
+                std::string instance_name = instance.mLabel;
+
+                BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+                if (importerDebug)
+                {
+                    // Useful for debugging generalized complaints below about total submeshes which don't have enough
+                    // context to address exactly what needs to be fixed to move towards compliance with the rules.
+                    //
+                    LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: "   << cur_verts     << LL_ENDL;
+                    LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris:  "   << cur_tris      << LL_ENDL;
+                    LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: "   << cur_submeshes << LL_ENDL;
+
+                    LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin();
+                    while (mat_iter != lod_model->mMaterialList.end())
+                    {
+                        LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL;
+                        mat_iter++;
+                    }
+                }
+
+                //add this model to the lod total
+				total_tris[i] += cur_tris;
+				total_verts[i] += cur_verts;
+				total_submeshes[i] += cur_submeshes;
+
+				//store this model's counts to asset data
+				tris[i].push_back(cur_tris);
+				verts[i].push_back(cur_verts);
+				submeshes[i].push_back(cur_submeshes);
 			}
 		}
-	}
+    }
 
 	if (mMaxTriangleLimit == 0)
 	{
@@ -4354,37 +2684,48 @@ void LLModelPreview::updateStatusMessages()
 		const LLVector4a scale(0.5f);
 		for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)
 		{ //for each model in the lod
-			if (mModel[lod][i]->mPhysics.mHull.empty())
+			if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
 			{ //no decomp exists
 				S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
 				for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)
 				{ //for each submesh (face), add triangles and vertices to current total
-					const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
-					for (S32 k = 0; k < face.mNumIndices && !has_degenerate; )
+					LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+					for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; )
 					{
-						LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale);
-						LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale);
-						LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale);
+						U16 index_a = face.mIndices[k+0];
+						U16 index_b = face.mIndices[k+1];
+						U16 index_c = face.mIndices[k+2];
+
+						LLVector4a v1; v1.setMul(face.mPositions[index_a], scale);
+						LLVector4a v2; v2.setMul(face.mPositions[index_b], scale);
+						LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
 
 						if (ll_is_degenerate(v1,v2,v3))
 						{
 							has_degenerate = true;
 						}
+						else
+						{
+							k += 3;
+						}
 					}
 				}
 			}
 		}
 	}
-	
+
 	mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
 
 	std::string mesh_status_na = mFMP->getString("mesh_status_na");
 
 	S32 upload_status[LLModel::LOD_HIGH+1];
 
-	bool upload_ok = true;
+	mModelNoErrors = true;
 
-	for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
+	const U32 lod_high = LLModel::LOD_HIGH;
+	U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]);
+
+	for (S32 lod = 0; lod <= lod_high; ++lod)
 	{
 		upload_status[lod] = 0;
 
@@ -4397,7 +2738,7 @@ void LLModelPreview::updateStatusMessages()
 		}
 		else
 		{
-			if (lod == LLModel::LOD_HIGH)
+			if (lod == lod_high)
 			{
 				upload_status[lod] = 2;
 				message = "mesh_status_missing_lod";
@@ -4418,8 +2759,6 @@ void LLModelPreview::updateStatusMessages()
 			mFMP->childSetValue(lod_vertices_name[lod], mesh_status_na);
 		}
 
-		const U32 lod_high = LLModel::LOD_HIGH;
-
 		if (lod != lod_high)
 		{
 			if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
@@ -4427,6 +2766,13 @@ void LLModelPreview::updateStatusMessages()
 				message = "mesh_status_submesh_mismatch";
 				upload_status[lod] = 2;
 			}
+			else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count)
+			{//number of submodels is different, not all faces are matched correctly.
+				message = "mesh_status_submesh_mismatch";
+				upload_status[lod] = 2;
+				// Note: Submodels in instance were loaded from higher LOD and as result face count
+				// returns same value and total_submeshes[lod] is identical to high_lod one.
+			}
 			else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size())
 			{ //number of meshes is different
 				message = "mesh_status_mesh_mismatch";
@@ -4447,7 +2793,7 @@ void LLModelPreview::updateStatusMessages()
 				{
 					//too many vertices in this lod
 					message = "mesh_status_too_many_vertices";
-					upload_status[lod] = 2;
+					upload_status[lod] = 1;
 				}
 			}
 		}
@@ -4459,7 +2805,7 @@ void LLModelPreview::updateStatusMessages()
 
 		if (upload_status[lod] >= 2)
 		{
-			upload_ok = false;
+			mModelNoErrors = false;
 		}
 
 		if (lod == mPreviewLOD)
@@ -4473,23 +2819,41 @@ void LLModelPreview::updateStatusMessages()
 	}
 
 
-	//make sure no hulls have more than 256 points in them
-	for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
+	//warn if hulls have more than 256 points in them
+	BOOL physExceededVertexLimit = FALSE;
+	for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
 	{
 		LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
 
-		for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)
+		if (mdl)
 		{
-			if (mdl->mPhysics.mHull[j].size() > 256)
+			for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j)
 			{
-				upload_ok = false;
+				if (mdl->mPhysics.mHull[j].size() > 256)
+				{
+					physExceededVertexLimit = TRUE;
+					LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL;
+					break;
+				}
 			}
 		}
 	}
+	mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit);
+	LLIconCtrl* physStatusIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
+	physStatusIcon->setVisible(physExceededVertexLimit);
+	if (physExceededVertexLimit)
+	{
+		mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded"));
+		LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning");
+		physStatusIcon->setImage(img);
+	}
 
-	bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false;
+	if (getLoadState() >= LLModelLoader::ERROR_PARSING)
+	{
+		mModelNoErrors = false;
+		LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL;
+	}
 
-	bool skinAndRigOk = true;
 	bool uploadingSkin		     = mFMP->childGetValue("upload_skin").asBoolean();
 	bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
 
@@ -4497,19 +2861,23 @@ void LLModelPreview::updateStatusMessages()
 	{
 		if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
 		{
-			skinAndRigOk = false;
-		}	
+			mModelNoErrors = false;
+			LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL;
+		}
 	}
-	
-	if(upload_ok && mModelLoader)
+
+	if(mModelNoErrors && mModelLoader)
 	{
 		if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
 		{
-			upload_ok = false ;
+			// Some textures are still loading, prevent upload until they are done
+			mModelNoErrors = false;
 		}
 	}
 
-	if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate)
+	// Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics
+	// current use of has_degenerate won't block upload permanently - later checks will restore the button
+	if (!mModelNoErrors || has_degenerate)
 	{
 		mFMP->childDisable("ok_btn");
 	}
@@ -4851,7 +3219,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 		LLModel* base_mdl = *base_iter;
 		base_iter++;
 
-		for (S32 i = 0, e = mdl->getNumVolumeFaces(); i < e; ++i)
+		S32 num_faces = mdl->getNumVolumeFaces();
+		for (S32 i = 0; i < num_faces; ++i)
 		{
 			const LLVolumeFace &vf = mdl->getVolumeFace(i);
 			U32 num_vertices = vf.mNumVertices;
@@ -4946,23 +3315,23 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 
 void LLModelPreview::update()
 {
-	if (mDirty)
+    if (mGenLOD)
 	{
-		mDirty = false;
-		mResourceCost = calcResourceCost();
+		mGenLOD = false;
+		genLODs();
 		refresh();
 		updateStatusMessages();
 	}
 
-	if (mGenLOD)
+	if (mDirty)
 	{
-		mGenLOD = false;
-		genLODs();
+		mDirty = false;
+		mResourceCost = calcResourceCost();
 		refresh();
 		updateStatusMessages();
 	}
-
 }
+
 //-----------------------------------------------------------------------------
 // getTranslationForJointOffset()
 //-----------------------------------------------------------------------------
@@ -4996,10 +3365,79 @@ void LLModelPreview::createPreviewAvatar( void )
 	}
 	else
 	{
-		LL_INFOS()<<"Failed to create preview avatar for upload model window"<<LL_ENDL;
+		LL_INFOS() << "Failed to create preview avatar for upload model window" << LL_ENDL;
 	}
 }
 
+//static
+U32 LLModelPreview::countRootModels(LLModelLoader::model_list models)
+{
+	U32 root_models = 0;
+	model_list::iterator model_iter = models.begin();
+	while (model_iter != models.end())
+	{
+		LLModel* mdl = *model_iter;
+		if (mdl && mdl->mSubmodelID == 0)
+		{
+			root_models++;
+		}
+		model_iter++;
+	}
+	return root_models;
+}
+
+void LLModelPreview::loadedCallback(
+	LLModelLoader::scene& scene,
+	LLModelLoader::model_list& model_list,
+	S32 lod,
+	void* opaque)
+{
+	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+	if (pPreview && !LLModelPreview::sIgnoreLoadedCallback)
+	{
+		pPreview->loadModelCallback(lod);
+	}	
+}
+
+void LLModelPreview::stateChangedCallback(U32 state,void* opaque)
+{
+	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+	if (pPreview)
+	{
+	 pPreview->setLoadState(state);
+	}
+}
+
+LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque)
+{
+	LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+	if (pPreview)
+	{
+		return pPreview->getPreviewAvatar()->getJoint(str);
+	}
+	return NULL;
+}
+
+U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque)
+{
+	(void)opaque;
+
+	if (material.mDiffuseMapFilename.size())
+	{
+		material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >;
+		LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData));
+
+		tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
+		tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE);
+		tex->forceToSaveRawImage(0, F32_MAX);
+		material.setDiffuseMap(tex->getID()); // record tex ID
+		return 1;
+	}
+
+	material.mOpaqueData = NULL;
+	return 0;	
+}
+
 void LLModelPreview::addEmptyFace( LLModel* pTarget )
 {
 	U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
@@ -5245,7 +3683,7 @@ BOOL LLModelPreview::render()
 			}
 			else
 			{
-				LL_INFOS(" ") << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
+				LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
 				regen = TRUE;
 			}
 		}
@@ -5255,24 +3693,6 @@ BOOL LLModelPreview::render()
 			genBuffers(mPreviewLOD, skin_weight);
 		}
 
-		//make sure material lists all match
-		for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
-		{
-			if (mBaseModel.size() == mModel[i].size())
-			{
-				for (U32 j = 0; j < mBaseModel.size(); ++j)
-				{
-					int refFaceCnt = 0;
-					int modelFaceCnt = 0;
-										
-					if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
-					{
-						mFMP->childDisable( "calculate_btn" );
-					}
-				}
-			}
-		}
-
 		if (!skin_weight)
 		{
 			for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
@@ -5281,62 +3701,63 @@ BOOL LLModelPreview::render()
 
 				LLModel* model = instance.mLOD[mPreviewLOD];
 
-				if (!model)
-				{
-					continue;
-				}
+					if (!model)
+					{
+						continue;
+					}
 
-				gGL.pushMatrix();
-				LLMatrix4 mat = instance.mTransform;
+					gGL.pushMatrix();
+					LLMatrix4 mat = instance.mTransform;
 
-				gGL.multMatrix((GLfloat*) mat.mMatrix);
+					gGL.multMatrix((GLfloat*) mat.mMatrix);
 
-				for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i)
-				{
-					LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-				
-					buffer->setBuffer(type_mask & buffer->getTypeMask());
 
-					if (textures)
+					U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
+					for (U32 i = 0; i < num_models; ++i)
 					{
-						int materialCnt = instance.mModel->mMaterialList.size();
-						if ( i < materialCnt )
+						LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
+				
+						buffer->setBuffer(type_mask & buffer->getTypeMask());
+
+						if (textures)
 						{
-							const std::string& binding = instance.mModel->mMaterialList[i];						
-							const LLImportMaterial& material = instance.mMaterial[binding];
+							int materialCnt = instance.mModel->mMaterialList.size();
+							if ( i < materialCnt )
+							{
+								const std::string& binding = instance.mModel->mMaterialList[i];						
+								const LLImportMaterial& material = instance.mMaterial[binding];
 
-							gGL.diffuseColor4fv(material.mDiffuseColor.mV);
+								gGL.diffuseColor4fv(material.mDiffuseColor.mV);
 
-							if (material.mDiffuseMap.notNull())
-							{
-								if (material.mDiffuseMap->getDiscardLevel() > -1)
+								// Find the tex for this material, bind it, and add it to our set
+								//
+								LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+								if (tex)
 								{
-									gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
-									mTextureSet.insert(material.mDiffuseMap.get());
+									mTextureSet.insert(tex);
 								}
 							}
 						}
-					}
-					else
-					{
-						gGL.diffuseColor4f(1,1,1,1);
-					}
-
-					buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
-					gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-					gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
+						else
+						{
+							gGL.diffuseColor4f(1,1,1,1);
+						}
 
-					if (edges)
-					{
-						glLineWidth(3.f);
-						glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 						buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
-						glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-						glLineWidth(1.f);
+						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+						gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
+
+						if (edges)
+						{
+							glLineWidth(3.f);
+							glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+							buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+							glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+							glLineWidth(1.f);
+						}
 					}
+					gGL.popMatrix();
 				}
-				gGL.popMatrix();
-			}
 
 			if (physics)
 			{
@@ -5364,97 +3785,99 @@ BOOL LLModelPreview::render()
 
 						LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
 
-						if (!model)
-						{
-							continue;
-						}
+							if (!model)
+							{
+								continue;
+							}
 
-						gGL.pushMatrix();
-						LLMatrix4 mat = instance.mTransform;
+							gGL.pushMatrix();
+							LLMatrix4 mat = instance.mTransform;
 
 						gGL.multMatrix((GLfloat*) mat.mMatrix);
 
 
-						bool render_mesh = true;
+							bool render_mesh = true;
 
-						LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
-						if (decomp)
-						{
-							LLMutexLock(decomp->mMutex);
+							LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+							if (decomp)
+							{
+								LLMutexLock(decomp->mMutex);
 
-							LLModel::Decomposition& physics = model->mPhysics;
+								LLModel::Decomposition& physics = model->mPhysics;
 
-							if (!physics.mHull.empty())
-							{
-								render_mesh = false;
+								if (!physics.mHull.empty())
+								{
+									render_mesh = false;
 
-								if (physics.mMesh.empty())
-								{ //build vertex buffer for physics mesh
-									gMeshRepo.buildPhysicsMesh(physics);
-								}
+									if (physics.mMesh.empty())
+									{ //build vertex buffer for physics mesh
+										gMeshRepo.buildPhysicsMesh(physics);
+									}
 						
-								if (!physics.mMesh.empty())
-								{ //render hull instead of mesh
-									for (U32 i = 0; i < physics.mMesh.size(); ++i)
-									{
-										if (explode > 0.f)
+									if (!physics.mMesh.empty())
+									{ //render hull instead of mesh
+										for (U32 i = 0; i < physics.mMesh.size(); ++i)
 										{
-											gGL.pushMatrix();
+											if (explode > 0.f)
+											{
+												gGL.pushMatrix();
 
-											LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
-											offset *= explode;
+												LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+												offset *= explode;
 
-											gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
-										}
+												gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+											}
 
-										static std::vector<LLColor4U> hull_colors;
+											static std::vector<LLColor4U> hull_colors;
 
-										if (i+1 >= hull_colors.size())
-										{
-											hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
-										}
+											if (i+1 >= hull_colors.size())
+											{
+												hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
+											}
 
-										gGL.diffuseColor4ubv(hull_colors[i].mV);
-										LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+											gGL.diffuseColor4ubv(hull_colors[i].mV);
+											LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
 
-										if (explode > 0.f)
-										{
-											gGL.popMatrix();
+											if (explode > 0.f)
+											{
+												gGL.popMatrix();
+											}
 										}
 									}
 								}
 							}
-						}
-
-						if (render_mesh)
-						{
-							if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
-							{
-								genBuffers(LLModel::LOD_PHYSICS, false);
-							}
-							for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+						
+							if (render_mesh)
 							{
-								LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+								if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+								{
+									genBuffers(LLModel::LOD_PHYSICS, false);
+								}
 
-								gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-								gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
+								U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
+								for (U32 i = 0; i < num_models; ++i)
+								{
+									LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
 
-								buffer->setBuffer(type_mask & buffer->getTypeMask());
-								buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+									gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+									gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
 
-								gGL.diffuseColor3f(1.f, 1.f, 0.f);
+									buffer->setBuffer(type_mask & buffer->getTypeMask());
+									buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
 
-								glLineWidth(2.f);
-								glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-								buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+									gGL.diffuseColor3f(1.f, 1.f, 0.f);
 
-								glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-								glLineWidth(1.f);
+									glLineWidth(2.f);
+									glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+									buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+
+									glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+									glLineWidth(1.f);
+								}
 							}
-						}
 
-						gGL.popMatrix();
-					}
+							gGL.popMatrix();
+						}
 
 					glLineWidth(3.f);
 					glPointSize(8.f);
@@ -5635,20 +4058,20 @@ BOOL LLModelPreview::render()
 								position[j] = v;
 							}
 
-							llassert(model->mMaterialList.size() > i);
+							llassert(model->mMaterialList.size() > i); 
 							const std::string& binding = instance.mModel->mMaterialList[i];
 							const LLImportMaterial& material = instance.mMaterial[binding];
 
 							buffer->setBuffer(type_mask & buffer->getTypeMask());
 							gGL.diffuseColor4fv(material.mDiffuseColor.mV);
 							gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-							if (material.mDiffuseMap.notNull())
+
+							// Find the tex for this material, bind it, and add it to our set
+							//
+							LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+							if (tex)
 							{
-								if (material.mDiffuseMap->getDiscardLevel() > -1)
-								{
-									gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
-									mTextureSet.insert(material.mDiffuseMap.get());
-								}
+								mTextureSet.insert(tex);
 							}
 						
 							buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
@@ -5763,14 +4186,14 @@ void LLFloaterModelPreview::onReset(void* user_data)
 	LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data;
 	fmp->childDisable("reset_btn");
 	LLModelPreview* mp = fmp->mModelPreview;
-	std::string filename = mp->mLODFile[3]; 
+	std::string filename = mp->mLODFile[LLModel::LOD_HIGH]; 
 
 	fmp->resetDisplayOptions();
 	//reset model preview
 	fmp->initModelPreview();
 
 	mp = fmp->mModelPreview;
-	mp->loadModel(filename,3,true);
+	mp->loadModel(filename,LLModel::LOD_HIGH,true);
 }
 
 //static
@@ -5864,7 +4287,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
 	}
 	
 	mUploadBtn->setVisible(!visible);
-	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+	mUploadBtn->setEnabled(isModelUploadAllowed());
 
 	if (visible)
 	{
@@ -5930,7 +4353,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
 	childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger()));
 	childSetVisible("upload_fee", true);
 	childSetVisible("price_breakdown", true);
-	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+	mUploadBtn->setEnabled(isModelUploadAllowed());
 }
 
 void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason)
@@ -5954,6 +4377,16 @@ void LLFloaterModelPreview::onModelUploadFailure()
 	mUploadBtn->setEnabled(true);
 }
 
+bool LLFloaterModelPreview::isModelUploadAllowed()
+{
+	bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty();
+	if (mModelPreview)
+	{
+		allow_upload &= mModelPreview->mModelNoErrors;
+	}
+	return allow_upload;
+}
+
 S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)
 {
 	if (mContinue)
@@ -6003,8 +4436,17 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
 	// BAP HACK: handle "" for case that  MeshUploadFlag cap is broken.
 	mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status));
 
-	//mUploadBtn->setEnabled(mHasUploadPerm);
-	mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+    if (!mHasUploadPerm) 
+    {
+        LL_WARNS() << "Upload permission set to false because upload_status=\"" << upload_status << "\"" << LL_ENDL;
+    }
+    else if (mHasUploadPerm && mUploadModelUrl.empty())
+    {
+        LL_WARNS() << "Upload permission set to true but uploadModelUrl is empty!" << LL_ENDL;
+    }
+
+	// isModelUploadAllowed() includes mHasUploadPerm
+	mUploadBtn->setEnabled(isModelUploadAllowed());
 	getChild<LLTextBox>("warning_title")->setVisible(!mHasUploadPerm);
 	getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm);
 }
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 618748bd4ea417e2d3d6504cdc9057b6f52d0939..7a518c798b17977cb96d15ff596ec2d5b3a08864 100755
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -37,6 +37,8 @@
 #include "llviewermenufile.h"
 #include "llfloatermodeluploadbase.h"
 
+#include "lldaeloader.h"
+
 class LLComboBox;
 class LLJoint;
 class LLViewerJointMesh;
@@ -45,103 +47,18 @@ class LLTextBox;
 class LLVertexBuffer;
 class LLModelPreview;
 class LLFloaterModelPreview;
+class DAE;
 class daeElement;
 class domProfile_COMMON;
 class domInstance_geometry;
 class domNode;
 class domTranslate;
 class domController;
+class domSkin;
+class domMesh;
 class LLMenuButton;
 class LLToggleableMenu;
 
-typedef std::map<std::string, LLMatrix4> JointTransformMap;
-typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
-
-const S32 NUM_LOD = 4;
-
-class LLModelLoader : public LLThread
-{
-public:
-	typedef enum
-	{
-		STARTING = 0,
-		READING_FILE,
-		CREATING_FACES,
-		GENERATING_VERTEX_BUFFERS,
-		GENERATING_LOD,
-		DONE,
-		ERROR_PARSING, //basically loading failed
-		ERROR_MATERIALS,
-	} eLoadState;
-
-	U32 mState;
-	std::string mFilename;
-	S32 mLod;
-	LLModelPreview* mPreview;
-	LLMatrix4 mTransform;
-	BOOL mFirstTransform;
-	LLVector3 mExtents[2];
-	bool mTrySLM;
-	
-	std::map<daeElement*, LLPointer<LLModel> > mModel;
-	
-	typedef std::vector<LLPointer<LLModel> > model_list;
-	model_list mModelList;
-
-	typedef std::vector<LLModelInstance> model_instance_list;
-	
-	typedef std::map<LLMatrix4, model_instance_list > scene;
-
-	scene mScene;
-
-	typedef std::queue<LLPointer<LLModel> > model_queue;
-
-	//queue of models that need a physics rep
-	model_queue mPhysicsQ;
-
-	LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, 
-				   std::deque<std::string>& jointsFromNodes );
-	~LLModelLoader() ;
-
-	virtual void run();
-	bool doLoadModel();
-	bool loadFromSLM(const std::string& filename);
-	void loadModelCallback();
-
-	void loadTextures() ; //called in the main thread.
-	void processElement(daeElement* element, bool& badElement);
-	std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
-	LLImportMaterial profileToMaterial(domProfile_COMMON* material);
-	std::string getElementLabel(daeElement *element);
-	LLColor4 getDaeColor(daeElement* element);
-	
-	daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
-	
-	bool isNodeAJoint( domNode* pNode );
-	void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
-	void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
-	void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
-	void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform );
-
-	void setLoadState(U32 state);
-
-	void buildJointToNodeMappingFromScene( daeElement* pRoot );
-	void processJointToNodeMapping( domNode* pNode );
-	void processChildJoints( domNode* pParentNode );
-
-	//map of avatar joints as named in COLLADA assets to internal joint names
-	std::map<std::string, std::string> mJointMap;
-	JointTransformMap& mJointList;	
-	std::deque<std::string>& mJointsFromNode;
-
-	S32 mNumOfFetchingTextures ; //updated in the main thread
-	bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
-
-private:
-	static std::list<LLModelLoader*> sActiveLoaderList;
-	static bool isAlive(LLModelLoader* loader) ;
-};
-
 class LLFloaterModelPreview : public LLFloaterModelUploadBase
 {
 public:
@@ -172,6 +89,7 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase
 	BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); 
 	
 	/*virtual*/ void onOpen(const LLSD& key);
+	/*virtual*/ void onClose(bool app_quitting);
 
 	static void onMouseCaptureLostModelPreview(LLMouseHandler*);
 	static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
@@ -210,6 +128,8 @@ class LLFloaterModelPreview : public LLFloaterModelUploadBase
 
 	/*virtual*/ void onModelUploadFailure();
 
+	bool isModelUploadAllowed();
+
 protected:
 	friend class LLModelPreview;
 	friend class LLMeshFilePicker;
@@ -359,21 +279,14 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	void setHasPivot( bool val ) { mHasPivot = val; }
 	void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
 
-	//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
-	void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
-	void critiqueJointToNodeMappingFromScene( void  );
 	//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
 	//Accessors for joint position upload friendly rigs
 	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
 	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
-	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
-	//Determines if a rig is a legacy from the joint list
-	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );	
+
 	//Accessors for the legacy rigs
 	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
-	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }	
-	//Verify that a controller matches vertex counts
-	bool verifyController( domController* pController );
+	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }		
 
 	static void	textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
 	
@@ -388,6 +301,16 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	
 	LLVector3 getTranslationForJointOffset( std::string joint );
 
+	static bool 		sIgnoreLoadedCallback;
+
+protected:
+
+	static void			loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque);
+	static void			stateChangedCallback(U32 state, void* opaque);
+
+	static LLJoint*	lookupJointByName(const std::string&, void* opaque);
+	static U32			loadTextures(LLImportMaterial& material, void* opaque);
+
 private:
 	//Utility function for controller vertex compare
 	bool verifyCount( int expected, int result );
@@ -395,6 +318,8 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	void		createPreviewAvatar( void );
 	//Accessor for the dummy avatar
 	LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
+	// Count amount of original models, excluding sub-models
+	static U32 countRootModels(LLModelLoader::model_list models);
 
  protected:
 	friend class LLModelLoader;
@@ -416,13 +341,15 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	LLVector3	mPreviewTarget;
 	LLVector3	mPreviewScale;
 	S32			mPreviewLOD;
+	S32			mPhysicsSearchLOD;
 	U32			mResourceCost;
 	std::string mLODFile[LLModel::NUM_LODS];
 	bool		mLoading;
 	U32			mLoadState;
 	bool		mResetJoints;
 	bool		mRigParityWithScene;
-	
+	bool		mModelNoErrors;
+
 	std::map<std::string, bool> mViewOption;
 
 	//GLOD object parameters (must rebuild object if these change)
@@ -459,7 +386,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 	U32 mMaxTriangleLimit;
 	
 	LLMeshUploadThread::instance_list mUploadData;
-	std::set<LLViewerFetchedTexture* > mTextureSet;
+	std::set<LLViewerFetchedTexture * > mTextureSet;
 
 	//map of vertex buffers to models (one vertex buffer in vector per face in model
 	std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
@@ -478,10 +405,9 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
 
 	bool		mLastJointUpdate;
 
-	std::deque<std::string> mMasterJointList;
-	std::deque<std::string> mMasterLegacyJointList;
-	std::deque<std::string> mJointsFromNode;
-	JointTransformMap		mJointTransformMap;
+	JointSet				mJointsFromNode;
+	JointTransformMap	mJointTransformMap;
+
 	LLPointer<LLVOAvatar>	mPreviewAvatar;
 };
 
diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp
index 22a8ac47057b636530235ff15322ec57116757ff..0fe97fd610f9b41579f09906c2e3325772aa734e 100755
--- a/indra/newview/llfloatermodeluploadbase.cpp
+++ b/indra/newview/llfloatermodeluploadbase.cpp
@@ -30,6 +30,7 @@
 #include "llagent.h"
 #include "llviewerregion.h"
 #include "llnotificationsutil.h"
+#include "llcorehttputil.h"
 
 LLFloaterModelUploadBase::LLFloaterModelUploadBase(const LLSD& key)
 :LLFloater(key),
@@ -47,7 +48,8 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions()
 		LL_INFOS()<< typeid(*this).name()
 				  << "::requestAgentUploadPermissions() requesting for upload model permissions from: "
 				  << url << LL_ENDL;
-		LLHTTPClient::get(url, new LLUploadModelPermissionsResponder(getPermObserverHandle()));
+        LLCoros::instance().launch("LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro",
+            boost::bind(&LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro, this, url, getPermObserverHandle()));
 	}
 	else
 	{
@@ -58,3 +60,34 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissions()
 		mHasUploadPerm = true;
 	}
 }
+
+void LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro(std::string url,
+    LLHandle<LLUploadPermissionsObserver> observerHandle)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("MeshUploadFlag", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    LLUploadPermissionsObserver* observer = observerHandle.get();
+
+    if (!observer)
+    { 
+        LL_WARNS("MeshUploadFlag") << "Unable to get observer after call to '" << url << "' aborting." << LL_ENDL;
+    }
+
+    if (!status)
+    {
+        observer->setPermissonsErrorStatus(status.getStatus(), status.getMessage());
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    observer->onPermissionsReceived(result);
+}
diff --git a/indra/newview/llfloatermodeluploadbase.h b/indra/newview/llfloatermodeluploadbase.h
index d9a887968783f06749466660c6aa463e9ad562fc..0d4c834122325d56ab1bc62457ca1fbfc0465ac5 100755
--- a/indra/newview/llfloatermodeluploadbase.h
+++ b/indra/newview/llfloatermodeluploadbase.h
@@ -28,6 +28,8 @@
 #define LL_LLFLOATERMODELUPLOADBASE_H
 
 #include "lluploadfloaterobservers.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLFloaterModelUploadBase : public LLFloater, public LLUploadPermissionsObserver, public LLWholeModelFeeObserver, public LLWholeModelUploadObserver
 {
@@ -54,6 +56,8 @@ class LLFloaterModelUploadBase : public LLFloater, public LLUploadPermissionsObs
 	// requests agent's permissions to upload model
 	void requestAgentUploadPermissions();
 
+    void requestAgentUploadPermissionsCoro(std::string url, LLHandle<LLUploadPermissionsObserver> observerHandle);
+
 	std::string mUploadModelUrl;
 	bool mHasUploadPerm;
 };
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 0cca715fe25d94ebd2673c37f010d838ffb80df5..135bbb335e41fa9e03cc914566eb492eb18f524c 100755
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -164,14 +164,18 @@ void LLFloaterNameDesc::onBtnOK( )
 	void *nruserdata = NULL;
 	std::string display_name = LLStringUtil::null;
 
-	upload_new_resource(mFilenameAndPath, // file
-			    getChild<LLUICtrl>("name_form")->getValue().asString(), 
-			    getChild<LLUICtrl>("description_form")->getValue().asString(), 
-			    0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
-			    LLFloaterPerms::getNextOwnerPerms("Uploads"),
-				LLFloaterPerms::getGroupPerms("Uploads"),
-				LLFloaterPerms::getEveryonePerms("Uploads"),
-			    display_name, callback, expected_upload_cost, nruserdata);
+    LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+            mFilenameAndPath,
+            getChild<LLUICtrl>("name_form")->getValue().asString(), 
+            getChild<LLUICtrl>("description_form")->getValue().asString(), 0,
+            LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+            LLFloaterPerms::getNextOwnerPerms("Uploads"),
+            LLFloaterPerms::getGroupPerms("Uploads"),
+            LLFloaterPerms::getEveryonePerms("Uploads"),
+            expected_upload_cost));
+
+    upload_new_resource(uploadInfo, callback, nruserdata);
+
 	closeFloater(false);
 }
 
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
deleted file mode 100755
index b7b1634a5fbd907961d76afad02205486a33f4e7..0000000000000000000000000000000000000000
--- a/indra/newview/llfloateroutbox.cpp
+++ /dev/null
@@ -1,623 +0,0 @@
-/** 
- * @file llfloateroutbox.cpp
- * @brief Implementation of the merchant outbox window
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloateroutbox.h"
-
-#include "llfloaterreg.h"
-#include "llfolderview.h"
-#include "llinventorybridge.h"
-#include "llinventorymodelbackgroundfetch.h"
-#include "llinventoryobserver.h"
-#include "llinventorypanel.h"
-#include "llmarketplacefunctions.h"
-#include "llnotificationhandler.h"
-#include "llnotificationmanager.h"
-#include "llnotificationsutil.h"
-#include "lltextbox.h"
-#include "lltransientfloatermgr.h"
-#include "lltrans.h"
-#include "llviewernetwork.h"
-#include "llwindowshade.h"
-
-
-///----------------------------------------------------------------------------
-/// LLOutboxNotification class
-///----------------------------------------------------------------------------
-
-LLNotificationsUI::LLOutboxNotification::LLOutboxNotification()
-	: LLSystemNotificationHandler("Outbox", "outbox")
-{
-}
-
-bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)
-{
-	LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
-	
-	outbox_floater->showNotification(notify);
-
-	return false;
-}
-
-void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p)
-{
-	LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
-	if (notification_handler)
-	{
-		notification_handler->onDelete(p);
-	}
-}
-
-///----------------------------------------------------------------------------
-/// LLOutboxAddedObserver helper class
-///----------------------------------------------------------------------------
-
-class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver
-{
-public:
-	LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater)
-		: LLInventoryCategoryAddedObserver()
-		, mOutboxFloater(outboxFloater)
-	{
-	}
-	
-	void done()
-	{
-		for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
-		{
-			LLViewerInventoryCategory* added_category = *it;
-			
-			LLFolderType::EType added_category_type = added_category->getPreferredType();
-			
-			if (added_category_type == LLFolderType::FT_OUTBOX)
-			{
-				mOutboxFloater->initializeMarketPlace();
-			}
-		}
-	}
-	
-private:
-	LLFloaterOutbox *	mOutboxFloater;
-};
-
-///----------------------------------------------------------------------------
-/// LLFloaterOutbox
-///----------------------------------------------------------------------------
-
-LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
-	: LLFloater(key)
-	, mCategoriesObserver(NULL)
-	, mCategoryAddedObserver(NULL)
-	, mImportBusy(false)
-	, mImportButton(NULL)
-	, mInventoryFolderCountText(NULL)
-	, mInventoryImportInProgress(NULL)
-	, mInventoryPlaceholder(NULL)
-	, mInventoryText(NULL)
-	, mInventoryTitle(NULL)
-	, mOutboxId(LLUUID::null)
-	, mOutboxItemCount(0)
-	, mOutboxTopLevelDropZone(NULL)
-	, mWindowShade(NULL)
-{
-}
-
-LLFloaterOutbox::~LLFloaterOutbox()
-{
-	if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
-	{
-		gInventory.removeObserver(mCategoriesObserver);
-	}
-	delete mCategoriesObserver;
-	
-	if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
-	{
-		gInventory.removeObserver(mCategoryAddedObserver);
-	}
-	delete mCategoryAddedObserver;
-}
-
-BOOL LLFloaterOutbox::postBuild()
-{
-	mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
-	mInventoryImportInProgress = getChild<LLView>("import_progress_indicator");
-	mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
-	mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text");
-	mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
-	
-	mImportButton = getChild<LLButton>("outbox_import_btn");
-	mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
-
-	mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
-
-	LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
-
-	// Observe category creation to catch outbox creation (moot if already existing)
-	mCategoryAddedObserver = new LLOutboxAddedObserver(this);
-	gInventory.addObserver(mCategoryAddedObserver);
-	
-    // Setup callbacks for importer
-	LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
-    importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
-    importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
-    importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
-    
-	return TRUE;
-}
-
-void LLFloaterOutbox::cleanOutbox()
-{
-    // Note: we cannot delete the mOutboxInventoryPanel as that point
-    // as this is called through callback observers of the panel itself.
-    // Doing so would crash rapidly.
-	
-	// Invalidate the outbox data
-    mOutboxId.setNull();
-    mOutboxItemCount = 0;
-}
-
-void LLFloaterOutbox::onClose(bool app_quitting)
-{
-	if (mWindowShade)
-	{
-		delete mWindowShade;
-
-		mWindowShade = NULL;
-	}
-}
-
-void LLFloaterOutbox::onOpen(const LLSD& key)
-{
-	//
-	// Initialize the Market Place or go update the outbox
-	//
-	if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED)
-	{
-		initializeMarketPlace();
-	}
-	else 
-	{
-		setupOutbox();
-	}
-	
-	//
-	// Update the floater view
-	//
-	updateView();
-	
-	//
-	// Trigger fetch of outbox contents
-	//
-	fetchOutboxContents();
-}
-
-void LLFloaterOutbox::onFocusReceived()
-{
-	fetchOutboxContents();
-}
-
-void LLFloaterOutbox::fetchOutboxContents()
-{
-	if (mOutboxId.notNull())
-	{
-		LLInventoryModelBackgroundFetch::instance().start(mOutboxId);
-	}
-}
-
-void LLFloaterOutbox::setupOutbox()
-{
-	if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)
-	{
-		// If we are *not* a merchant or we have no market place connection established yet, do nothing
-		return;
-	}
-		
-	// We are a merchant. Get the outbox, create it if needs be.
-	LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true);
-	if (outbox_id.isNull())
-	{
-		// We should never get there unless the inventory fails badly
-		LL_ERRS() << "Inventory problem: failure to create the outbox for a merchant!" << LL_ENDL;
-		return;
-	}
-    
-    // Consolidate Merchant Outbox
-    // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually
-    gInventory.consolidateForType(outbox_id, LLFolderType::FT_OUTBOX);
-    
-    if (outbox_id == mOutboxId)
-    {
-        LL_WARNS() << "Inventory warning: Merchant outbox already set" << LL_ENDL;
-        return;
-    }
-    mOutboxId = outbox_id;
-
-	// No longer need to observe new category creation
-	if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
-	{
-		gInventory.removeObserver(mCategoryAddedObserver);
-		delete mCategoryAddedObserver;
-		mCategoryAddedObserver = NULL;
-	}
-	llassert(!mCategoryAddedObserver);
-	
-	// Create observer for outbox modifications : clear the old one and create a new one
-	if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
-	{
-		gInventory.removeObserver(mCategoriesObserver);
-		delete mCategoriesObserver;
-	}
-    mCategoriesObserver = new LLInventoryCategoriesObserver();
-    gInventory.addObserver(mCategoriesObserver);
-    mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
-	llassert(mCategoriesObserver);
-	
-	// Set up the outbox inventory view
-	LLInventoryPanel* inventory_panel = mOutboxInventoryPanel.get();
-    if (inventory_panel)
-    {
-        delete inventory_panel;
-    }
-    inventory_panel = LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", mInventoryPlaceholder->getParent(), LLInventoryPanel::child_registry_t::instance());
-    mOutboxInventoryPanel = inventory_panel->getInventoryPanelHandle();
-	llassert(mOutboxInventoryPanel.get() != NULL);
-	
-	// Reshape the inventory to the proper size
-	LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect();
-	inventory_panel->setShape(inventory_placeholder_rect);
-	
-	// Set the sort order newest to oldest
-	inventory_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME);	
-	inventory_panel->getFilter().markDefault();
-    
-	// Get the content of the outbox
-	fetchOutboxContents();
-}
-
-void LLFloaterOutbox::initializeMarketPlace()
-{
-	//
-	// Initialize the marketplace import API
-	//
-	LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
-    if (!importer.isInitialized())
-    {
-        importer.initialize();
-    }
-}
-
-void LLFloaterOutbox::setStatusString(const std::string& statusString)
-{
-	llassert(mInventoryFolderCountText != NULL);
-
-	mInventoryFolderCountText->setText(statusString);
-}
-
-void LLFloaterOutbox::updateFolderCount()
-{
-	if (mOutboxInventoryPanel.get() && mOutboxId.notNull())
-	{
-        U32 item_count = 0;
-
-        if (mOutboxId.notNull())
-        {
-            LLInventoryModel::cat_array_t * cats;
-            LLInventoryModel::item_array_t * items;
-            gInventory.getDirectDescendentsOf(mOutboxId, cats, items);
-
-            item_count = cats->size() + items->size();
-        }
-	
-        mOutboxItemCount = item_count;
-    }
-    else
-    {
-        // If there's no outbox, the number of items in it should be set to 0 for consistency
-        mOutboxItemCount = 0;
-    }
-
-	if (!mImportBusy)
-	{
-		updateFolderCountStatus();
-	}
-}
-
-void LLFloaterOutbox::updateFolderCountStatus()
-{
-	if (mOutboxInventoryPanel.get() && mOutboxId.notNull())
-	{
-		switch (mOutboxItemCount)
-		{
-			case 0:	setStatusString(getString("OutboxFolderCount0"));	break;
-			case 1:	setStatusString(getString("OutboxFolderCount1"));	break;
-			default:
-			{
-				std::string item_count_str = llformat("%d", mOutboxItemCount);
-				
-				LLStringUtil::format_map_t args;
-				args["[NUM]"] = item_count_str;
-				
-				setStatusString(getString("OutboxFolderCountN", args));
-				break;
-			}
-		}
-	}
-
-	mImportButton->setEnabled(mOutboxItemCount > 0);
-}
-
-void LLFloaterOutbox::updateView()
-{
-	updateFolderCount();
-	LLInventoryPanel* panel = mOutboxInventoryPanel.get();
-
-	if (mOutboxItemCount > 0)
-	{
-		panel->setVisible(TRUE);
-		mInventoryPlaceholder->setVisible(FALSE);
-		mOutboxTopLevelDropZone->setVisible(TRUE);
-	}
-	else
-	{
-		if (panel)
-		{
-			panel->setVisible(FALSE);
-		}
-		
-		// Show the drop zone if there is an outbox folder
-		mOutboxTopLevelDropZone->setVisible(mOutboxId.notNull());
-
-		mInventoryPlaceholder->setVisible(TRUE);
-
-		std::string outbox_text;
-		std::string outbox_title;
-		std::string outbox_tooltip;
-		
-		const LLSD& subs = getMarketplaceStringSubstitutions();
-		U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus();
-		
-		if (mOutboxId.notNull())
-		{
-            // Does the outbox needs recreation?
-            if ((mOutboxInventoryPanel.get() == NULL) || !gInventory.getCategory(mOutboxId))
-            {
-                setupOutbox();
-            }
-			// "Outbox is empty!" message strings
-			outbox_text = LLTrans::getString("InventoryOutboxNoItems", subs);
-			outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
-		}
-		else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING)
-		{
-			// "Initializing!" message strings
-			outbox_text = LLTrans::getString("InventoryOutboxInitializing", subs);
-			outbox_title = LLTrans::getString("InventoryOutboxInitializingTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip");
-		}
-		else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT)
-		{
-			// "Not a merchant!" message strings
-			outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs);
-			outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
-		}
-		else
-		{
-			// "Errors!" message strings
-			outbox_text = LLTrans::getString("InventoryOutboxError", subs);
-			outbox_title = LLTrans::getString("InventoryOutboxErrorTitle");
-			outbox_tooltip = LLTrans::getString("InventoryOutboxErrorTooltip");
-		}
-		
-		mInventoryText->setValue(outbox_text);
-		mInventoryTitle->setValue(outbox_title);
-		mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip);
-	}
-}
-
-bool isAccepted(EAcceptance accept)
-{
-	return (accept >= ACCEPT_YES_COPY_SINGLE);
-}
-
-BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
-										EDragAndDropType cargo_type,
-										void* cargo_data,
-										EAcceptance* accept,
-										std::string& tooltip_msg)
-{
-	if ((mOutboxInventoryPanel.get() == NULL) ||
-		(mWindowShade && mWindowShade->isShown()) ||
-		LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() ||
-        mOutboxId.isNull())
-	{
-		return FALSE;
-	}
-	
-	LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-	BOOL handled = (handled_view != NULL);
-
-	// Determine if the mouse is inside the inventory panel itself or just within the floater
-	bool pointInInventoryPanel = false;
-	bool pointInInventoryPanelChild = false;
-	LLInventoryPanel* panel = mOutboxInventoryPanel.get();
-	LLFolderView* root_folder = panel->getRootFolder();
-	if (panel->getVisible())
-	{
-		S32 inv_x, inv_y;
-		localPointToOtherView(x, y, &inv_x, &inv_y, panel);
-
-		pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y);
-
-		LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true);
-		pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder);
-	}
-	
-	// Pass all drag and drop for this floater to the outbox inventory control
-	if (!handled || !isAccepted(*accept))
-	{
-		// Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel
-		// (otherwise the inventory panel itself will handle the drag and drop operation, without any override)
-		if (!pointInInventoryPanel)
-		{
-			handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-		}
-
-		mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
-	}
-	else
-	{
-		mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild);
-	}
-	
-	return handled;
-}
-
-BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask)
-{
-	mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-
-	return LLFloater::handleHover(x, y, mask);
-}
-
-void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
-{
-	mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-
-	LLFloater::onMouseLeave(x, y, mask);
-}
-
-void LLFloaterOutbox::onImportButtonClicked()
-{
-    if (mOutboxInventoryPanel.get())
-    {
-        mOutboxInventoryPanel.get()->clearSelection();
-    }
-    
-	mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport();
-}
-
-void LLFloaterOutbox::onOutboxChanged()
-{
-    LLViewerInventoryCategory* category = gInventory.getCategory(mOutboxId);
-	if (mOutboxId.notNull() && category)
-    {
-        fetchOutboxContents();
-        updateView();
-    }
-    else
-    {
-        cleanOutbox();
-    }
-}
-
-void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
-{
-	if (status == MarketplaceErrorCodes::IMPORT_DONE)
-	{
-		LLNotificationsUtil::add("OutboxImportComplete");
-	}
-	else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
-	{
-		const LLSD& subs = getMarketplaceStringSubstitutions();
-
-		LLNotificationsUtil::add("OutboxImportHadErrors", subs);
-	}
-	else
-	{
-		char status_string[16];
-		sprintf(status_string, "%d", status);
-		
-		LLSD subs;
-		subs["[ERROR_CODE]"] = status_string;
-		
-		LLNotificationsUtil::add("OutboxImportFailed", subs);
-	}
-	
-	updateView();
-}
-
-void LLFloaterOutbox::importStatusChanged(bool inProgress)
-{
-	if (mOutboxId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT))
-	{
-		setupOutbox();
-	}
-	
-	if (inProgress)
-	{
-		if (mImportBusy)
-		{
-			setStatusString(getString("OutboxImporting"));
-		}
-		else
-		{
-			setStatusString(getString("OutboxInitializing"));
-		}
-		
-		mImportBusy = true;
-		mImportButton->setEnabled(false);
-		mInventoryImportInProgress->setVisible(true);
-	}
-	else
-	{
-		setStatusString("");
-		mImportBusy = false;
-		mImportButton->setEnabled(mOutboxItemCount > 0);
-		mInventoryImportInProgress->setVisible(false);
-	}
-	
-	updateView();
-}
-
-void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)
-{
-	if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)
-	{
-		char status_string[16];
-		sprintf(status_string, "%d", status);
-		
-		LLSD subs;
-		subs["[ERROR_CODE]"] = status_string;
-		
-		LLNotificationsUtil::add("OutboxInitFailed", subs);
-	}
-	
-	updateView();
-}
-
-void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)
-{
-	LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
-	llassert(notification_handler);
-	
-	notification_handler->processNotification(notification);
-}
-
-
-
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
deleted file mode 100755
index 2cf69fc3cc3411888724676aadf84e352dd32f1f..0000000000000000000000000000000000000000
--- a/indra/newview/llfloateroutbox.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/** 
- * @file llfloateroutbox.h
- * @brief Implementation of the merchant outbox window
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * ABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFLOATEROUTBOX_H
-#define LL_LLFLOATEROUTBOX_H
-
-#include "llfloater.h"
-#include "llfoldertype.h"
-#include "llinventoryfilter.h"
-#include "llnotificationptr.h"
-
-
-class LLButton;
-class LLInventoryCategoriesObserver;
-class LLInventoryCategoryAddedObserver;
-class LLInventoryPanel;
-class LLLoadingIndicator;
-class LLNotification;
-class LLTextBox;
-class LLView;
-class LLWindowShade;
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFloaterOutbox
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFloaterOutbox : public LLFloater
-{
-public:
-	LLFloaterOutbox(const LLSD& key);
-	~LLFloaterOutbox();
-	
-	void initializeMarketPlace();
-
-	// virtuals
-	BOOL postBuild();
-	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
-						   EDragAndDropType cargo_type,
-						   void* cargo_data,
-						   EAcceptance* accept,
-						   std::string& tooltip_msg);
-	
-	void showNotification(const LLNotificationPtr& notification);
-
-	BOOL handleHover(S32 x, S32 y, MASK mask);
-	void onMouseLeave(S32 x, S32 y, MASK mask);
-
-protected:
-	void setupOutbox();
-    void cleanOutbox();
-	void fetchOutboxContents();
-
-	void importReportResults(U32 status, const LLSD& content);
-	void importStatusChanged(bool inProgress);
-	void initializationReportError(U32 status, const LLSD& content);
-	
-	void onClose(bool app_quitting);
-	void onOpen(const LLSD& key);
-
-	void onFocusReceived();
-
-	void onImportButtonClicked();
-	void onOutboxChanged();
-	
-	void setStatusString(const std::string& statusString);
-	
-	void updateFolderCount();
-	void updateFolderCountStatus();
-	void updateView();
-
-private:
-	LLInventoryCategoriesObserver *		mCategoriesObserver;
-	LLInventoryCategoryAddedObserver *	mCategoryAddedObserver;
-	
-	bool			mImportBusy;
-	LLButton *		mImportButton;
-	
-	LLTextBox *		mInventoryFolderCountText;
-	LLView *		mInventoryImportInProgress;
-	LLView *		mInventoryPlaceholder;
-	LLTextBox *		mInventoryText;
-	LLTextBox *		mInventoryTitle;
-	
-	LLUUID				mOutboxId;
-	LLHandle<LLInventoryPanel> mOutboxInventoryPanel;
-	U32					mOutboxItemCount;
-	LLPanel *			mOutboxTopLevelDropZone;
-	
-	LLWindowShade *	mWindowShade;
-};
-
-#endif // LL_LLFLOATEROUTBOX_H
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 042cf470704a5fe27e937245e3a6930e11b76764..31c2a6f9aaf8971d61ff6492db63a89820c40956 100755
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -37,6 +37,7 @@
 #include "llnotificationsutil.h"
 #include "llsdserialize.h"
 #include "llvoavatar.h"
+#include "llcorehttputil.h"
 
 LLFloaterPerms::LLFloaterPerms(const LLSD& seed)
 : LLFloater(seed)
@@ -166,41 +167,6 @@ void LLFloaterPermsDefault::onCommitCopy(const LLSD& user_data)
 	xfer->setEnabled(copyable);
 }
 
-class LLFloaterPermsResponder : public LLHTTPClient::Responder
-{
-public:
-	LLFloaterPermsResponder(): LLHTTPClient::Responder() {}
-private:
-	static	std::string sPreviousReason;
-
-	void httpFailure()
-	{
-		const std::string& reason = getReason();
-		// Do not display the same error more than once in a row
-		if (reason != sPreviousReason)
-		{
-			sPreviousReason = reason;
-			LLSD args;
-			args["REASON"] = reason;
-			LLNotificationsUtil::add("DefaultObjectPermissions", args);
-		}
-	}
-
-	void httpSuccess()
-	{
-		//const LLSD& content = getContent();
-		//dump_sequential_xml("perms_responder_result.xml", content);
-
-		// Since we have had a successful POST call be sure to display the next error message
-		// even if it is the same as a previous one.
-		sPreviousReason = "";
-		LLFloaterPermsDefault::setCapSent(true);
-		LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL;
-	}
-};
-
-	std::string	LLFloaterPermsResponder::sPreviousReason;
-
 void LLFloaterPermsDefault::sendInitialPerms()
 {
 	if(!mCapSent)
@@ -215,23 +181,8 @@ void LLFloaterPermsDefault::updateCap()
 
 	if(!object_url.empty())
 	{
-		LLSD report = LLSD::emptyMap();
-		report["default_object_perm_masks"]["Group"] =
-			(LLSD::Integer)LLFloaterPerms::getGroupPerms(sCategoryNames[CAT_OBJECTS]);
-		report["default_object_perm_masks"]["Everyone"] =
-			(LLSD::Integer)LLFloaterPerms::getEveryonePerms(sCategoryNames[CAT_OBJECTS]);
-		report["default_object_perm_masks"]["NextOwner"] =
-			(LLSD::Integer)LLFloaterPerms::getNextOwnerPerms(sCategoryNames[CAT_OBJECTS]);
-
-        {
-            LL_DEBUGS("ObjectPermissionsFloater") << "Sending default permissions to '"
-                                                  << object_url << "'\n";
-            std::ostringstream sent_perms_log;
-            LLSDSerialize::toPrettyXML(report, sent_perms_log);
-            LL_CONT << sent_perms_log.str() << LL_ENDL;
-        }
-    
-		LLHTTPClient::post(object_url, report, new LLFloaterPermsResponder());
+        LLCoros::instance().launch("LLFloaterPermsDefault::updateCapCoro",
+            boost::bind(&LLFloaterPermsDefault::updateCapCoro, object_url));
 	}
     else
     {
@@ -239,6 +190,57 @@ void LLFloaterPermsDefault::updateCap()
     }
 }
 
+/*static*/
+void LLFloaterPermsDefault::updateCapCoro(std::string url)
+{
+    static std::string previousReason;
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD postData = LLSD::emptyMap();
+    postData["default_object_perm_masks"]["Group"] =
+        (LLSD::Integer)LLFloaterPerms::getGroupPerms(sCategoryNames[CAT_OBJECTS]);
+    postData["default_object_perm_masks"]["Everyone"] =
+        (LLSD::Integer)LLFloaterPerms::getEveryonePerms(sCategoryNames[CAT_OBJECTS]);
+    postData["default_object_perm_masks"]["NextOwner"] =
+        (LLSD::Integer)LLFloaterPerms::getNextOwnerPerms(sCategoryNames[CAT_OBJECTS]);
+
+    {
+        LL_DEBUGS("ObjectPermissionsFloater") << "Sending default permissions to '"
+            << url << "'\n";
+        std::ostringstream sent_perms_log;
+        LLSDSerialize::toPrettyXML(postData, sent_perms_log);
+        LL_CONT << sent_perms_log.str() << LL_ENDL;
+    }
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        const std::string& reason = status.toString();
+        // Do not display the same error more than once in a row
+        if (reason != previousReason)
+        {
+            previousReason = reason;
+            LLSD args;
+            args["REASON"] = reason;
+            LLNotificationsUtil::add("DefaultObjectPermissions", args);
+        }
+        return;
+    }
+
+    // Since we have had a successful POST call be sure to display the next error message
+    // even if it is the same as a previous one.
+    previousReason.clear();
+    LLFloaterPermsDefault::setCapSent(true);
+    LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL;
+}
+
 void LLFloaterPermsDefault::setCapSent(bool cap_sent)
 {
 	mCapSent = cap_sent;
diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h
index 2bb0a19dc1c21db96b11b5b3ec99706e7d54a70f..e866b6de7de11314c6ec44d15854d685227645a5 100755
--- a/indra/newview/llfloaterperms.h
+++ b/indra/newview/llfloaterperms.h
@@ -29,6 +29,8 @@
 #define LL_LLFLOATERPERMPREFS_H
 
 #include "llfloater.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLFloaterPerms : public LLFloater
 {
@@ -80,6 +82,8 @@ enum Categories
 	void refresh();
 
 	static const std::string sCategoryNames[CAT_LAST]; 
+    static void updateCapCoro(std::string url);
+
 
 	// cached values only for implementing cancel.
 	bool mShareWithGroup[CAT_LAST];
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
index 40757a4d049dcd1a59e3bdbbad6bcd5ad56e147c..271fb2f9a356559587b09c472c68f820b2289785 100755
--- a/indra/newview/llfloaterregiondebugconsole.cpp
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -30,11 +30,11 @@
 #include "llfloaterregiondebugconsole.h"
 
 #include "llagent.h"
-#include "llhttpclient.h"
 #include "llhttpnode.h"
 #include "lllineeditor.h"
 #include "lltexteditor.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
 // Two versions of the sim console API are supported.
 //
@@ -68,58 +68,6 @@ namespace
 	const std::string CONSOLE_NOT_SUPPORTED(
 		"This region does not support the simulator console.");
 
-	// This responder handles the initial response. Unless error() is called
-	// we assume that the simulator has received our request. Error will be
-	// called if this request times out.
-	class AsyncConsoleResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(AsyncConsoleResponder);
-	protected:
-		/* virtual */
-		void httpFailure()
-		{
-			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
-			sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
-		}
-	};
-
-	class ConsoleResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(ConsoleResponder);
-	public:
-		ConsoleResponder(LLTextEditor *output) : mOutput(output)
-		{
-		}
-
-	protected:
-		/*virtual*/
-		void httpFailure()
-		{
-			LL_WARNS("Console") << dumpResponse() << LL_ENDL;
-			if (mOutput)
-			{
-				mOutput->appendText(
-					UNABLE_TO_SEND_COMMAND + PROMPT,
-					false);
-			}
-		}
-
-		/*virtual*/
-		void httpSuccess()
-		{
-			const LLSD& content = getContent();
-			LL_DEBUGS("Console") << content << LL_ENDL;
-			if (mOutput)
-			{
-				mOutput->appendText(
-					content.asString() + PROMPT, false);
-			}
-		}
-
-	public:
-		LLTextEditor * mOutput;
-	};
-
 	// This handles responses for console commands sent via the asynchronous
 	// API.
 	class ConsoleResponseNode : public LLHTTPNode
@@ -202,26 +150,57 @@ void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param)
 		}
 		else
 		{
-			// Using SimConsole (deprecated)
-			LLHTTPClient::post(
-				url,
-				LLSD(input->getText()),
-				new ConsoleResponder(mOutput));
+            LLSD postData = LLSD(input->getText());
+            LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, postData,
+                boost::bind(&LLFloaterRegionDebugConsole::onConsoleSuccess, this, _1),
+                boost::bind(&LLFloaterRegionDebugConsole::onConsoleError, this, _1));
 		}
 	}
 	else
 	{
-		// Using SimConsoleAsync
-		LLHTTPClient::post(
-			url,
-			LLSD(input->getText()),
-			new AsyncConsoleResponder);
+        LLSD postData = LLSD(input->getText());
+        LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, postData,
+            NULL,
+            boost::bind(&LLFloaterRegionDebugConsole::onAsyncConsoleError, this, _1));
+
 	}
 
 	mOutput->appendText(text, false);
 	input->clear();
 }
 
+void LLFloaterRegionDebugConsole::onAsyncConsoleError(LLSD result)
+{
+    LL_WARNS("Console") << UNABLE_TO_SEND_COMMAND << LL_ENDL;
+    sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
+}
+
+void LLFloaterRegionDebugConsole::onConsoleError(LLSD result)
+{
+    LL_WARNS("Console") << UNABLE_TO_SEND_COMMAND << LL_ENDL;
+    if (mOutput)
+    {
+        mOutput->appendText(
+            UNABLE_TO_SEND_COMMAND + PROMPT,
+            false);
+    }
+
+}
+
+void LLFloaterRegionDebugConsole::onConsoleSuccess(LLSD result)
+{
+    if (mOutput)
+    {
+        LLSD response = result;
+        if (response.isMap() && response.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT))
+        {
+            response = response[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
+        }
+        mOutput->appendText(
+            response.asString() + PROMPT, false);
+    }
+}
+
 void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output)
 {
 	mOutput->appendText(output + PROMPT, false);
diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h
index fd3af4152e94873d083257bf58a31b6de7e1893a..f55d9649243d1b8f117f441f9ca2c0cde5340c45 100755
--- a/indra/newview/llfloaterregiondebugconsole.h
+++ b/indra/newview/llfloaterregiondebugconsole.h
@@ -31,14 +31,13 @@
 #include <boost/signals2.hpp>
 
 #include "llfloater.h"
-#include "llhttpclient.h"
 
 class LLTextEditor;
 
 typedef boost::signals2::signal<
 	void (const std::string& output)> console_reply_signal_t;
 
-class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder
+class LLFloaterRegionDebugConsole : public LLFloater
 {
 public:
 	LLFloaterRegionDebugConsole(LLSD const & key);
@@ -56,6 +55,10 @@ class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Respo
  private:
 	void onReplyReceived(const std::string& output);
 
+    void onAsyncConsoleError(LLSD result);
+    void onConsoleError(LLSD result);
+    void onConsoleSuccess(LLSD result);
+
 	boost::signals2::connection mReplySignalConnection;
 };
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 5d1e01c1f7a864aa5e969e845738f638cfe3e558..94f3a45d88dd1d6411758b6caacc59962eea144d 100755
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -97,6 +97,7 @@
 #include "llpanelexperiencepicker.h"
 #include "llexperiencecache.h"
 #include "llpanelexperiences.h"
+#include "llcorehttputil.h"
 
 const S32 TERRAIN_TEXTURE_COUNT = 4;
 const S32 CORNER_COUNT = 4;
@@ -803,30 +804,6 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
 	return false;
 }
 
-class ConsoleRequestResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(ConsoleRequestResponder);
-protected:
-	/*virtual*/
-	void httpFailure()
-	{
-		LL_WARNS() << "error requesting mesh_rez_enabled " << dumpResponse() << LL_ENDL;
-	}
-};
-
-
-// called if this request times out.
-class ConsoleUpdateResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(ConsoleUpdateResponder);
-protected:
-	/* virtual */
-	void httpFailure()
-	{
-		LL_WARNS() << "error updating mesh enabled region setting " << dumpResponse() << LL_ENDL;
-	}
-};
-
 void LLFloaterRegionInfo::requestMeshRezInfo()
 {
 	std::string sim_console_url = gAgent.getRegion()->getCapability("SimConsoleAsync");
@@ -835,10 +812,8 @@ void LLFloaterRegionInfo::requestMeshRezInfo()
 	{
 		std::string request_str = "get mesh_rez_enabled";
 		
-		LLHTTPClient::post(
-			sim_console_url,
-			LLSD(request_str),
-			new ConsoleRequestResponder);
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(sim_console_url, LLSD(request_str),
+            "Requested mesh_rez_enabled", "Error requesting mesh_rez_enabled");
 	}
 }
 
@@ -874,7 +849,8 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
 		body["allow_parcel_changes"] = getChild<LLUICtrl>("allow_parcel_changes_check")->getValue();
 		body["block_parcel_search"] = getChild<LLUICtrl>("block_parcel_search_check")->getValue();
 
-		LLHTTPClient::post(url, body, new LLHTTPClient::Responder());
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
+            "Region info update posted.", "Region info update not posted.");
 	}
 	else
 	{
@@ -2303,36 +2279,6 @@ void LLPanelEstateInfo::getEstateOwner()
 }
 */
 
-class LLEstateChangeInfoResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLEstateChangeInfoResponder);
-public:
-	LLEstateChangeInfoResponder(LLPanelEstateInfo* panel)
-	{
-		mpPanel = panel->getHandle();
-	}
-	
-protected:
-	// if we get a normal response, handle it here
-	virtual void httpSuccess()
-	{
-		LL_INFOS("Windlight") << "Successfully committed estate info" << LL_ENDL;
-
-	    // refresh the panel from the database
-		LLPanelEstateInfo* panel = dynamic_cast<LLPanelEstateInfo*>(mpPanel.get());
-		if (panel)
-			panel->refresh();
-	}
-	
-	// if we get an error response
-	virtual void httpFailure()
-	{
-		LL_WARNS("Windlight") << dumpResponse() << LL_ENDL;
-	}
-private:
-	LLHandle<LLPanel> mpPanel;
-};
-
 const std::string LLPanelEstateInfo::getOwnerName() const
 {
 	return getChild<LLUICtrl>("estate_owner")->getValue().asString();
@@ -3640,29 +3586,6 @@ void LLPanelRegionExperiences::processResponse( const LLSD& content )
 
 }
 
-
-class LLRegionExperienceResponder : public LLHTTPClient::Responder
-{
-public:
-	typedef boost::function<void (const LLSD&)> callback_t;
-
-	callback_t mCallback;
-
-	LLRegionExperienceResponder(callback_t callback) : mCallback(callback) { }
-
-protected:
-	/*virtual*/ void httpSuccess()
-	{
-		mCallback(getContent());
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
-	}
-};
-
-
 // Used for both access add and remove operations, depending on the flag
 // passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.)
 // static
@@ -3745,6 +3668,13 @@ void LLPanelRegionExperiences::infoCallback(LLHandle<LLPanelRegionExperiences> h
 	}
 }
 
+/*static*/
+std::string LLPanelRegionExperiences::regionCapabilityQuery(LLViewerRegion* region, const std::string &cap)
+{
+    // region->getHandle()  How to get a region * from a handle?
+
+    return region->getCapability(cap);
+}
 
 bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
 {
@@ -3769,13 +3699,10 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
 	mTrusted->loading();
 	mTrusted->setReadonly(!allow_modify);
 
-	std::string url = region->getCapability("RegionExperiences");
-	if (!url.empty())
-	{
-		LLHTTPClient::get(url, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback, 
-			getDerivedHandle<LLPanelRegionExperiences>(), _1)));
-	}
-	return LLPanelRegionInfo::refreshFromRegion(region);
+    LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
+        boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
+
+    return LLPanelRegionInfo::refreshFromRegion(region);
 }
 
 LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
@@ -3793,18 +3720,15 @@ LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
 BOOL LLPanelRegionExperiences::sendUpdate()
 {
 	LLViewerRegion* region = gAgent.getRegion();
-	std::string url = region->getCapability("RegionExperiences");
-	if (!url.empty())
-	{
-		LLSD content;
 
-		content["allowed"]=addIds(mAllowed);
-		content["blocked"]=addIds(mBlocked);
-		content["trusted"]=addIds(mTrusted);
+    LLSD content;
 
-		LLHTTPClient::post(url, content, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback, 
-			getDerivedHandle<LLPanelRegionExperiences>(), _1)));
-	}
+	content["allowed"]=addIds(mAllowed);
+	content["blocked"]=addIds(mBlocked);
+	content["trusted"]=addIds(mTrusted);
+
+    LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
+        content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
 
 	return TRUE;
 }
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index e7b49d8553e616c08659227283cd43088819375b..3c74618fffc9e2204c620e250fee780f43757e07 100755
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -36,6 +36,7 @@
 #include "llextendedstatus.h"
 
 #include "llenvmanager.h" // for LLEnvironmentSettings
+#include "lleventcoro.h"
 
 class LLAvatarName;
 class LLDispatcher;
@@ -107,6 +108,8 @@ class LLFloaterRegionInfo : public LLFloater
 	
 	LLFloaterRegionInfo(const LLSD& seed);
 	~LLFloaterRegionInfo();
+
+
 	
 protected:
 	void onTabSelected(const LLSD& param);
@@ -476,6 +479,8 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
 private:
 	void refreshRegionExperiences();
 
+    static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap);
+
 	LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id);
 	static LLSD addIds( LLPanelExperienceListEditor* panel );
 
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 2f4d2a93b21d66280234ca75205f7f78b077bddd..1c2340b0efcc5e639516d631d1288b103c5b1e7e 100755
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -77,12 +77,66 @@
 #include "lluictrlfactory.h"
 #include "llviewernetwork.h"
 
-#include "llassetuploadresponders.h"
 #include "llagentui.h"
 
 #include "lltrans.h"
 #include "llexperiencecache.h"
 
+#include "llcorehttputil.h"
+#include "llviewerassetupload.h"
+
+
+//=========================================================================
+//-----------------------------------------------------------------------------
+// Support classes
+//-----------------------------------------------------------------------------
+class LLARScreenShotUploader : public LLResourceUploadInfo
+{
+public:
+    LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType);
+
+    virtual LLSD        prepareUpload();
+    virtual LLSD        generatePostBody();
+    virtual S32         getEconomyUploadCost();
+    virtual LLUUID      finishUpload(LLSD &result);
+
+    virtual bool        showInventoryPanel() const { return false; }
+    virtual std::string getDisplayName() const { return "Abuse Report"; }
+
+private:
+
+    LLSD    mReport;
+};
+
+LLARScreenShotUploader::LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType) :
+    LLResourceUploadInfo(assetId, assetType, "Abuse Report"),
+    mReport(report)
+{
+}
+
+LLSD LLARScreenShotUploader::prepareUpload()
+{
+    return LLSD().with("success", LLSD::Boolean(true));
+}
+
+LLSD LLARScreenShotUploader::generatePostBody()
+{   // The report was pregenerated and passed in the constructor.
+    return mReport;
+}
+
+S32 LLARScreenShotUploader::getEconomyUploadCost()
+{   // Abuse report screen shots do not cost anything to upload.
+    return 0;
+}
+
+LLUUID LLARScreenShotUploader::finishUpload(LLSD &result)
+{
+    /* *TODO$: Report success or failure. Carried over from previous todo on responder*/
+    return LLUUID::null;
+}
+
+
+//=========================================================================
 //-----------------------------------------------------------------------------
 // Globals
 //-----------------------------------------------------------------------------
@@ -214,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id)
 
 	if (LLUUID::null != mExperienceID)
 	{
-		const LLSD& experience = LLExperienceCache::get(mExperienceID);
+        const LLSD& experience = LLExperienceCache::instance().get(mExperienceID);
 		std::stringstream desc;
 
 		if(experience.isDefined())
@@ -706,59 +760,25 @@ void LLFloaterReporter::sendReportViaLegacy(const LLSD & report)
 	msg->sendReliable(regionp->getHost());
 }
 
-class LLUserReportScreenshotResponder : public LLAssetUploadResponder
+void LLFloaterReporter::finishedARPost(const LLSD &)
 {
-public:
-	LLUserReportScreenshotResponder(const LLSD & post_data, 
-									const LLUUID & vfile_id, 
-									LLAssetType::EType asset_type):
-	  LLAssetUploadResponder(post_data, vfile_id, asset_type)
-	{
-	}
-	void uploadFailed(const LLSD& content)
-	{
-		// *TODO pop up a dialog so the user knows their report screenshot didn't make it
-		LLUploadDialog::modalUploadFinished();
-	}
-	void uploadComplete(const LLSD& content)
-	{
-		// we don't care about what the server returns from this post, just clean up the UI
-		LLUploadDialog::modalUploadFinished();
-	}
-};
+    LLUploadDialog::modalUploadFinished();
 
-class LLUserReportResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLUserReportResponder);
-public:
-	LLUserReportResponder(): LLHTTPClient::Responder()  {}
-
-private:
-	void httpCompleted()
-	{
-		if (!isGoodStatus())
-		{
-			// *TODO do some user messaging here
-			LL_WARNS("UserReport") << dumpResponse() << LL_ENDL;
-		}
-		// we don't care about what the server returns
-		LLUploadDialog::modalUploadFinished();
-	}
-};
+}
 
 void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
 {
 	if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty())
-	{
+    {
 		// try to upload screenshot
-		LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, 
-															mResourceDatap->mAssetInfo.mUuid, 
-															mResourceDatap->mAssetInfo.mType));			
+        LLResourceUploadInfo::ptr_t uploadInfo(new  LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType));
+        LLViewerAssetUpload::EnqueueInventoryUpload(sshot_url, uploadInfo);
 	}
 	else
 	{
-		// screenshot not wanted or we don't have screenshot cap
-		LLHTTPClient::post(url, report, new LLUserReportResponder());			
+        LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t proc = boost::bind(&LLFloaterReporter::finishedARPost, _1);
+        LLUploadDialog::modalUploadDialog("Abuse Report");
+        LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, report, proc, proc);
 	}
 }
 
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index d857528f100a4369dd05ca518cc3d099c53b549f..1aff07bd372b623913841ed13ed3ab9bfe4855eb 100755
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -122,6 +122,8 @@ class LLFloaterReporter
 	void setFromAvatarID(const LLUUID& avatar_id);
 	void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name);
 
+    static void finishedARPost(const LLSD &);
+
 private:
 	EReportType		mReportType;
 	LLUUID 			mObjectID;
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 5fbdd75e970a829db7ff67265b641bf37e33be9f..7b8fc5b35bf53be4a970fbceb8ab51e06eed4704 100755
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -50,6 +50,7 @@
 #include "llviewerparcelmgr.h"
 #include "llviewerregion.h"
 #include "llviewerwindow.h"
+#include "llcorehttputil.h"
 
 ///----------------------------------------------------------------------------
 /// LLFloaterScriptLimits
@@ -179,372 +180,6 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
 {
 }
 
-///----------------------------------------------------------------------------
-// Responders
-///----------------------------------------------------------------------------
-
-void fetchScriptLimitsRegionInfoResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	//we don't need to test with a fake respose here (shouldn't anyway)
-
-#ifdef DUMP_REPLIES_TO_LLINFOS
-
-	LLSDNotationStreamer notation_streamer(content);
-	std::ostringstream nice_llsd;
-	nice_llsd << notation_streamer;
-
-	OSMessageBox(nice_llsd.str(), "main cap response:", 0);
-
-	LL_INFOS() << "main cap response:" << content << LL_ENDL;
-
-#endif
-
-	// at this point we have an llsd which should contain ether one or two urls to the services we want.
-	// first we look for the details service:
-	if(content.has("ScriptResourceDetails"))
-	{
-		LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo));
-	}
-	else
-	{
-		LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
-		if(!instance)
-		{
-			LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
-		}
-	}
-
-	// then the summary service:
-	if(content.has("ScriptResourceSummary"))
-	{
-		LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo));
-	}
-}
-
-void fetchScriptLimitsRegionInfoResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-}
-
-void fetchScriptLimitsRegionSummaryResponder::httpSuccess()
-{
-	const LLSD& content_ref = getContent();
-#ifdef USE_FAKE_RESPONSES
-
-	LLSD fake_content;
-	LLSD summary = LLSD::emptyMap();
-	LLSD available = LLSD::emptyArray();
-	LLSD available_urls = LLSD::emptyMap();
-	LLSD available_memory = LLSD::emptyMap();
-	LLSD used = LLSD::emptyArray();
-	LLSD used_urls = LLSD::emptyMap();
-	LLSD used_memory = LLSD::emptyMap();
-
-	used_urls["type"] = "urls";
-	used_urls["amount"] = FAKE_NUMBER_OF_URLS;
-	available_urls["type"] = "urls";
-	available_urls["amount"] = FAKE_AVAILABLE_URLS;
-	used_memory["type"] = "memory";
-	used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
-	available_memory["type"] = "memory";
-	available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
-
-//summary response:{'summary':{'available':[{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'},{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'}],'used':[{'amount':i329,'type':'urls'},{'amount':i66741,'type':'memory'}]}}
-
-	used.append(used_urls);
-	used.append(used_memory);
-	available.append(available_urls);
-	available.append(available_memory);
-
-	summary["available"] = available;
-	summary["used"] = used;
-	
-	fake_content["summary"] = summary;
-
-	const LLSD& content = fake_content;
-
-#else
-
-	const LLSD& content = content_ref;
-
-#endif
-
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-
-
-#ifdef DUMP_REPLIES_TO_LLINFOS
-
-	LLSDNotationStreamer notation_streamer(content);
-	std::ostringstream nice_llsd;
-	nice_llsd << notation_streamer;
-
-	OSMessageBox(nice_llsd.str(), "summary response:", 0);
-
-	LL_WARNS() << "summary response:" << *content << LL_ENDL;
-
-#endif
-
-	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
-	if(!instance)
-	{
-		LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
-	}
-	else
-	{
-		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
-		if(tab)
-		{
-			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
-			if(panel_memory)
-			{
-				panel_memory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
-
-				LLButton* btn = panel_memory->getChild<LLButton>("refresh_list_btn");
-				if(btn)
-				{
-					btn->setEnabled(true);
-				}
-
-				panel_memory->setRegionSummary(content);
-			}
-		}
-	}
-}
-
-void fetchScriptLimitsRegionSummaryResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-}
-
-void fetchScriptLimitsRegionDetailsResponder::httpSuccess()
-{
-	const LLSD& content_ref = getContent();
-#ifdef USE_FAKE_RESPONSES
-/*
-Updated detail service, ** denotes field added:
-
-result (map)
-+-parcels (array of maps)
-  +-id (uuid)
-  +-local_id (S32)**
-  +-name (string)
-  +-owner_id (uuid) (in ERS as owner, but owner_id in code)
-  +-objects (array of maps)
-    +-id (uuid)
-    +-name (string)
-	+-owner_id (uuid) (in ERS as owner, in code as owner_id)
-	+-owner_name (sting)**
-	+-location (map)**
-	  +-x (float)
-	  +-y (float)
-	  +-z (float)
-    +-resources (map) (this is wrong in the ERS but right in code)
-      +-type (string)
-      +-amount (int)
-*/
-	LLSD fake_content;
-	LLSD resource = LLSD::emptyMap();
-	LLSD location = LLSD::emptyMap();
-	LLSD object = LLSD::emptyMap();
-	LLSD objects = LLSD::emptyArray();
-	LLSD parcel = LLSD::emptyMap();
-	LLSD parcels = LLSD::emptyArray();
-
-	resource["urls"] = FAKE_NUMBER_OF_URLS;
-	resource["memory"] = FAKE_AMOUNT_OF_MEMORY;
-	
-	location["x"] = 128.0f;
-	location["y"] = 128.0f;
-	location["z"] = 0.0f;
-	
-	object["id"] = LLUUID("d574a375-0c6c-fe3d-5733-da669465afc7");
-	object["name"] = "Gabs fake Object!";
-	object["owner_id"] = LLUUID("8dbf2d41-69a0-4e5e-9787-0c9d297bc570");
-	object["owner_name"] = "Gabs Linden";
-	object["location"] = location;
-	object["resources"] = resource;
-
-	objects.append(object);
-
-	parcel["id"] = LLUUID("da05fb28-0d20-e593-2728-bddb42dd0160");
-	parcel["local_id"] = 42;
-	parcel["name"] = "Gabriel Linden\'s Sub Plot";
-	parcel["objects"] = objects;
-	parcels.append(parcel);
-
-	fake_content["parcels"] = parcels;
-	const LLSD& content = fake_content;
-
-#else
-
-	const LLSD& content = content_ref;
-
-#endif
-
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-
-#ifdef DUMP_REPLIES_TO_LLINFOS
-
-	LLSDNotationStreamer notation_streamer(content);
-	std::ostringstream nice_llsd;
-	nice_llsd << notation_streamer;
-
-	OSMessageBox(nice_llsd.str(), "details response:", 0);
-
-	LL_INFOS() << "details response:" << content << LL_ENDL;
-
-#endif
-
-	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
-
-	if(!instance)
-	{
-		LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
-	}
-	else
-	{
-		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
-		if(tab)
-		{
-			LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
-			if(panel_memory)
-			{
-				panel_memory->setRegionDetails(content);
-			}
-			else
-			{
-				LL_WARNS() << "Failed to get scriptlimits memory panel" << LL_ENDL;
-			}
-		}
-		else
-		{
-			LL_WARNS() << "Failed to get scriptlimits_panels" << LL_ENDL;
-		}
-	}
-}
-
-void fetchScriptLimitsRegionDetailsResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-}
-
-void fetchScriptLimitsAttachmentInfoResponder::httpSuccess()
-{
-	const LLSD& content_ref = getContent();
-
-#ifdef USE_FAKE_RESPONSES
-
-	// just add the summary, as that's all I'm testing currently!
-	LLSD fake_content = LLSD::emptyMap();
-	LLSD summary = LLSD::emptyMap();
-	LLSD available = LLSD::emptyArray();
-	LLSD available_urls = LLSD::emptyMap();
-	LLSD available_memory = LLSD::emptyMap();
-	LLSD used = LLSD::emptyArray();
-	LLSD used_urls = LLSD::emptyMap();
-	LLSD used_memory = LLSD::emptyMap();
-
-	used_urls["type"] = "urls";
-	used_urls["amount"] = FAKE_NUMBER_OF_URLS;
-	available_urls["type"] = "urls";
-	available_urls["amount"] = FAKE_AVAILABLE_URLS;
-	used_memory["type"] = "memory";
-	used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
-	available_memory["type"] = "memory";
-	available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
-
-	used.append(used_urls);
-	used.append(used_memory);
-	available.append(available_urls);
-	available.append(available_memory);
-
-	summary["available"] = available;
-	summary["used"] = used;
-	
-	fake_content["summary"] = summary;
-	fake_content["attachments"] = content_ref["attachments"];
-
-	const LLSD& content = fake_content;
-
-#else
-
-	const LLSD& content = content_ref;
-
-#endif
-
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-
-#ifdef DUMP_REPLIES_TO_LLINFOS
-
-	LLSDNotationStreamer notation_streamer(content);
-	std::ostringstream nice_llsd;
-	nice_llsd << notation_streamer;
-
-	OSMessageBox(nice_llsd.str(), "attachment response:", 0);
-	
-	LL_INFOS() << "attachment response:" << content << LL_ENDL;
-
-#endif
-
-	LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
-
-	if(!instance)
-	{
-		LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
-	}
-	else
-	{
-		LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
-		if(tab)
-		{
-			LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
-			if(panel)
-			{
-				panel->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
-
-				LLButton* btn = panel->getChild<LLButton>("refresh_list_btn");
-				if(btn)
-				{
-					btn->setEnabled(true);
-				}
-			
-				panel->setAttachmentDetails(content);
-			}
-			else
-			{
-				LL_WARNS() << "Failed to get script_limits_my_avatar_panel" << LL_ENDL;
-			}
-		}
-		else
-		{
-			LL_WARNS() << "Failed to get scriptlimits_panels" << LL_ENDL;
-		}
-	}
-}
-
-void fetchScriptLimitsAttachmentInfoResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-}
-
 ///----------------------------------------------------------------------------
 // Memory Panel
 ///----------------------------------------------------------------------------
@@ -564,12 +199,8 @@ BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
 	std::string url = gAgent.getRegion()->getCapability("LandResources");
 	if (!url.empty())
 	{
-		body["parcel_id"] = mParcelId;
-
-		LLSD info;
-		info["parcel_id"] = mParcelId;
-		LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info));
-				
+        LLCoros::instance().launch("LLPanelScriptLimitsRegionMemory::getLandScriptResourcesCoro",
+            boost::bind(&LLPanelScriptLimitsRegionMemory::getLandScriptResourcesCoro, this, url));
 		return TRUE;
 	}
 	else
@@ -578,6 +209,147 @@ BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
 	}
 }
 
+void LLPanelScriptLimitsRegionMemory::getLandScriptResourcesCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getLandScriptResourcesCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD postData;
+
+    postData["parcel_id"] = mParcelId;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Failed to get script resource info" << LL_ENDL;
+        return;
+    }
+
+    // We could retrieve these sequentially inline from this coroutine. But 
+    // since the original code retrieved them in parallel I'll spawn two 
+    // coroutines to do the retrieval. 
+
+    // The summary service:
+    if (result.has("ScriptResourceSummary"))
+    {
+        std::string urlResourceSummary = result["ScriptResourceSummary"].asString();
+        LLCoros::instance().launch("LLPanelScriptLimitsRegionMemory::getLandScriptSummaryCoro",
+            boost::bind(&LLPanelScriptLimitsRegionMemory::getLandScriptSummaryCoro, this, urlResourceSummary));
+    }
+
+    if (result.has("ScriptResourceDetails"))
+    {
+        std::string urlResourceDetails = result["ScriptResourceDetails"].asString();
+        LLCoros::instance().launch("LLPanelScriptLimitsRegionMemory::getLandScriptDetailsCoro",
+            boost::bind(&LLPanelScriptLimitsRegionMemory::getLandScriptDetailsCoro, this, urlResourceDetails));
+    }
+
+   
+}
+
+void LLPanelScriptLimitsRegionMemory::getLandScriptSummaryCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getLandScriptSummaryCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Unable to retrieve script summary." << LL_ENDL;
+        return;
+    }
+
+    LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+    if (!instance)
+    {
+        LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
+        return;
+    }
+
+    LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+    if (!tab)
+    {
+        LL_WARNS() << "Unable to access script limits tab" << LL_ENDL;
+        return;
+    }
+
+    LLPanelScriptLimitsRegionMemory* panelMemory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+    if (!panelMemory)
+    {
+        LL_WARNS() << "Unable to get memory panel." << LL_ENDL;
+        return;
+    }
+
+    panelMemory->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
+
+    LLButton* btn = panelMemory->getChild<LLButton>("refresh_list_btn");
+    if (btn)
+    {
+        btn->setEnabled(true);
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    panelMemory->setRegionSummary(result);
+
+}
+
+void LLPanelScriptLimitsRegionMemory::getLandScriptDetailsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getLandScriptDetailsCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Unable to retrieve script details." << LL_ENDL;
+        return;
+    }
+
+    LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+    if (!instance)
+    {
+        LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
+        return;
+    }
+
+    LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+    if (!tab)
+    {
+        LL_WARNS() << "Unable to access script limits tab" << LL_ENDL;
+        return;
+    }
+
+    LLPanelScriptLimitsRegionMemory* panelMemory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+
+    if (!panelMemory)
+    {
+        LL_WARNS() << "Unable to get memory panel." << LL_ENDL;
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    panelMemory->setRegionDetails(result);
+}
+
 void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data)
 {
 	if(!getLandScriptResources())
@@ -935,17 +707,8 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
 		std::string url = region->getCapability("RemoteParcelRequest");
 		if (!url.empty())
 		{
-			body["location"] = ll_sd_from_vector3(parcel_center);
-			if (!region_id.isNull())
-			{
-				body["region_id"] = region_id;
-			}
-			if (!pos_global.isExactlyZero())
-			{
-				U64 region_handle = to_region_handle(pos_global);
-				body["region_handle"] = ll_sd_from_U64(region_handle);
-			}
-			LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+            LLRemoteParcelInfoProcessor::getInstance()->requestRegionParcelInfo(url, 
+                region_id, parcel_center, pos_global, getObserverHandle());
 		}
 		else
 		{
@@ -1183,7 +946,8 @@ BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
 	std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
 	if (!url.empty())
 	{
-		LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder());
+        LLCoros::instance().launch("LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro",
+            boost::bind(&LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro, this, url));
 		return TRUE;
 	}
 	else
@@ -1192,6 +956,59 @@ BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
 	}
 }
 
+void LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL;
+        return;
+    }
+
+    LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+    if (!instance)
+    {
+        LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
+        return;
+    }
+
+    LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+    if (!tab)
+    {
+        LL_WARNS() << "Failed to get scriptlimits_panels" << LL_ENDL;
+        return;
+    }
+
+    LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+    if (!panel)
+    {
+        LL_WARNS() << "Failed to get script_limits_my_avatar_panel" << LL_ENDL;
+        return;
+    }
+
+    panel->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
+
+    LLButton* btn = panel->getChild<LLButton>("refresh_list_btn");
+    if (btn)
+    {
+        btn->setEnabled(true);
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    panel->setAttachmentDetails(result);
+}
+
+
 void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
 {
 	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index 5ba0185d329e2e132c54fefabf1edb85305f160e..e3cbbd185fc64b73d8b4f61ce7e7d4ee6f776c9e 100755
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -33,6 +33,8 @@
 #include "llhost.h"
 #include "llpanel.h"
 #include "llremoteparcelrequest.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLPanelScriptLimitsInfo;
 class LLTabContainer;
@@ -79,57 +81,6 @@ class LLPanelScriptLimitsInfo : public LLPanel
 	LLHost mHost;
 };
 
-/////////////////////////////////////////////////////////////////////////////
-// Responders
-/////////////////////////////////////////////////////////////////////////////
-
-class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(fetchScriptLimitsRegionInfoResponder);
-public:
-	fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
-
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-	LLSD mInfo;
-};
-
-class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(fetchScriptLimitsRegionSummaryResponder);
-public:
-	fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
-
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-	LLSD mInfo;
-};
-
-class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(fetchScriptLimitsRegionDetailsResponder);
-public:
-	fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
-
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-	LLSD mInfo;
-};
-
-class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(fetchScriptLimitsAttachmentInfoResponder);
-public:
-	fetchScriptLimitsAttachmentInfoResponder() {};
-
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-};
-
 /////////////////////////////////////////////////////////////////////////////
 // Memory panel
 /////////////////////////////////////////////////////////////////////////////
@@ -181,6 +132,10 @@ class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemote
 
 	std::vector<LLSD> mObjectListItems;
 
+    void getLandScriptResourcesCoro(std::string url);
+    void getLandScriptSummaryCoro(std::string url);
+    void getLandScriptDetailsCoro(std::string url);
+
 protected:
 
 // LLRemoteParcelInfoObserver interface:
@@ -225,6 +180,7 @@ class LLPanelScriptLimitsAttachment : public LLPanelScriptLimitsInfo
 	void clearList();
 
 private:
+    void getAttachmentLimitsCoro(std::string url);
 
 	bool mGotAttachmentMemoryUsed;
 	S32 mAttachmentMemoryMax;
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index c1c21c593e5b0071f61098150cb535e053c04c48..f6cfaf552264305a823a4dc2ec1f47b85e379b2e 100755
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -35,8 +35,6 @@
 // linden library includes
 #include "llbutton.h"
 #include "llevents.h"
-#include "llhttpclient.h"
-#include "llhttpconstants.h"
 #include "llnotificationsutil.h"
 #include "llradiogroup.h"
 #include "lltextbox.h"
@@ -45,7 +43,7 @@
 #include "llvfile.h"
 #include "message.h"
 #include "llstartup.h"              // login_alert_done
-
+#include "llcorehttputil.h"
 
 LLFloaterTOS::LLFloaterTOS(const LLSD& data)
 :	LLModalDialog( data["message"].asString() ),
@@ -57,57 +55,6 @@ LLFloaterTOS::LLFloaterTOS(const LLSD& data)
 {
 }
 
-// helper class that trys to download a URL from a web site and calls a method 
-// on parent class indicating if the web server is working or not
-class LLIamHere : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLIamHere);
-private:
-	LLIamHere( LLFloaterTOS* parent ) :
-	   mParent( parent )
-	{}
-
-	LLFloaterTOS* mParent;
-
-public:
-	static LLIamHere* build( LLFloaterTOS* parent )
-	{
-		return new LLIamHere( parent );
-	}
-	
-	virtual void  setParent( LLFloaterTOS* parentIn )
-	{
-		mParent = parentIn;
-	}
-	
-protected:
-	virtual void httpSuccess()
-	{
-		if ( mParent )
-		{
-			mParent->setSiteIsAlive( true );
-		}
-	}
-
-	virtual void httpFailure()
-	{
-		LL_DEBUGS("LLIamHere") << dumpResponse() << LL_ENDL;
-		if ( mParent )
-		{
-			// *HACK: For purposes of this alive check, 302 Found
-			// (aka Moved Temporarily) is considered alive.  The web site
-			// redirects this link to a "cache busting" temporary URL. JC
-			bool alive = (getStatus() == HTTP_FOUND);
-			mParent->setSiteIsAlive( alive );
-		}
-	}
-};
-
-// this is global and not a class member to keep crud out of the header file
-namespace {
-	LLPointer< LLIamHere > gResponsePtr = 0;
-};
-
 BOOL LLFloaterTOS::postBuild()
 {	
 	childSetAction("Continue", onContinue, this);
@@ -180,9 +127,6 @@ void LLFloaterTOS::setSiteIsAlive( bool alive )
 
 LLFloaterTOS::~LLFloaterTOS()
 {
-	// tell the responder we're not here anymore
-	if ( gResponsePtr )
-		gResponsePtr->setParent( 0 );
 }
 
 // virtual
@@ -243,9 +187,10 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
 		if(!mLoadingScreenLoaded)
 		{
 			mLoadingScreenLoaded = true;
+            std::string url(getString("real_url"));
 
-			gResponsePtr = LLIamHere::build( this );
-			LLHTTPClient::get( getString( "real_url" ), gResponsePtr );
+            LLCoros::instance().launch("LLFloaterTOS::testSiteIsAliveCoro",
+                boost::bind(&LLFloaterTOS::testSiteIsAliveCoro, this, url));
 		}
 		else if(mRealNavigateBegun)
 		{
@@ -257,3 +202,26 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
 	}
 }
 
+void LLFloaterTOS::testSiteIsAliveCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+
+    LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    // double not.  
+    // First ! returns a boolean error status, second ! is true if success result.
+    setSiteIsAlive(!!status); 
+}
+
+
diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h
index 47126d06a64859be60c6fdef68c9b60e00493b4b..2748b205130946cf8a9da286ad9828dced603c72 100755
--- a/indra/newview/llfloatertos.h
+++ b/indra/newview/llfloatertos.h
@@ -31,6 +31,8 @@
 #include "llassetstorage.h"
 #include "llmediactrl.h"
 #include <boost/function.hpp>
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLButton;
 class LLRadioGroup;
@@ -60,12 +62,15 @@ class LLFloaterTOS :
 	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
 
 private:
+    void testSiteIsAliveCoro(std::string url);
 
 	std::string		mMessage;
 	bool			mLoadingScreenLoaded;
 	bool			mSiteAlive;
 	bool			mRealNavigateBegun;
 	std::string		mReplyPumpName;
+
+
 };
 
 #endif // LL_LLFLOATERTOS_H
diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp
index 965d29b09cac78136617eb263469a5ce9f6e54b5..b1316e386df0ccb4262ac30409560dff2297c644 100755
--- a/indra/newview/llfloatertranslationsettings.cpp
+++ b/indra/newview/llfloatertranslationsettings.cpp
@@ -42,41 +42,6 @@
 #include "llnotificationsutil.h"
 #include "llradiogroup.h"
 
-class EnteredKeyVerifier : public LLTranslate::KeyVerificationReceiver
-{
-public:
-	EnteredKeyVerifier(LLTranslate::EService service, bool alert)
-	:	LLTranslate::KeyVerificationReceiver(service)
-	,	mAlert(alert)
-	{
-	}
-
-private:
-	/*virtual*/ void setVerificationStatus(bool ok)
-	{
-		LLFloaterTranslationSettings* floater =
-			LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
-
-		if (!floater)
-		{
-			LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
-			return;
-		}
-
-		switch (getService())
-		{
-		case LLTranslate::SERVICE_BING:
-			floater->setBingVerified(ok, mAlert);
-			break;
-		case LLTranslate::SERVICE_GOOGLE:
-			floater->setGoogleVerified(ok, mAlert);
-			break;
-		}
-	}
-
-	bool mAlert;
-};
-
 LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key)
 :	LLFloater(key)
 ,	mMachineTranslationCB(NULL)
@@ -231,11 +196,34 @@ void LLFloaterTranslationSettings::updateControlsEnabledState()
 	mOKBtn->setEnabled(!on || service_verified);
 }
 
+/*static*/
+void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert)
+{
+    LLFloaterTranslationSettings* floater =
+        LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
+
+    if (!floater)
+    {
+        LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
+        return;
+    }
+
+    switch (service)
+    {
+    case LLTranslate::SERVICE_BING:
+        floater->setBingVerified(ok, alert);
+        break;
+    case LLTranslate::SERVICE_GOOGLE:
+        floater->setGoogleVerified(ok, alert);
+        break;
+    }
+}
+
+
 void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert)
 {
-	LLTranslate::KeyVerificationReceiverPtr receiver =
-		new EnteredKeyVerifier((LLTranslate::EService) service, alert);
-	LLTranslate::verifyKey(receiver, key);
+    LLTranslate::verifyKey(static_cast<LLTranslate::EService>(service), key,
+        boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert));
 }
 
 void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control)
diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h
index b9bfd6265aff8f61845fd95ef8fe6dafca28f2c1..2a15eacdedafa50c8559f7442211ad929b2e4e48 100755
--- a/indra/newview/llfloatertranslationsettings.h
+++ b/indra/newview/llfloatertranslationsettings.h
@@ -61,6 +61,8 @@ class LLFloaterTranslationSettings : public LLFloater
 	void onBtnGoogleVerify();
 	void onBtnOK();
 
+    static void setVerificationStatus(int service, bool alert, bool ok);
+
 	LLCheckBoxCtrl* mMachineTranslationCB;
 	LLComboBox* mLanguageCombo;
 	LLLineEditor* mBingAPIKeyEditor;
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index e02e8eeb5ac800e8572a79260d887789e8c6278d..f2efef0c33fac1f3da88bb87d4d80b695e621918 100755
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -26,8 +26,6 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#include "llhttpclient.h"
-
 #include "llfloaterurlentry.h"
 
 #include "llpanellandmedia.h"
@@ -40,40 +38,10 @@
 #include "lluictrlfactory.h"
 #include "llwindow.h"
 #include "llviewerwindow.h"
+#include "llcorehttputil.h"
 
 static LLFloaterURLEntry* sInstance = NULL;
 
-// Move this to its own file.
-// helper class that tries to download a URL from a web site and calls a method
-// on the Panel Land Media and to discover the MIME type
-class LLMediaTypeResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLMediaTypeResponder);
-public:
-	LLMediaTypeResponder( const LLHandle<LLFloater> parent ) :
-		mParent( parent )
-	{}
-
-	LLHandle<LLFloater> mParent;
-
-private:
-	/* virtual */ void httpCompleted()
-	{
-		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
-		std::string::size_type idx1 = media_type.find_first_of(";");
-		std::string mime_type = media_type.substr(0, idx1);
-
-		// Set empty type to none/none.  Empty string is reserved for legacy parcels
-		// which have no mime type set.
-		std::string resolved_mime_type = ! mime_type.empty() ? mime_type : LLMIMETypes::getDefaultMimeType();
-		LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
-		if ( floater_url_entry )
-		{
-			floater_url_entry->headerFetchComplete( getStatus(), resolved_mime_type );
-		}
-	}
-};
-
 //-----------------------------------------------------------------------------
 // LLFloaterURLEntry()
 //-----------------------------------------------------------------------------
@@ -225,8 +193,8 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
 	if(!media_url.empty() && 
 	   (scheme == "http" || scheme == "https"))
 	{
-		LLHTTPClient::getHeaderOnly( media_url,
-			new LLMediaTypeResponder(self->getHandle()));
+        LLCoros::instance().launch("LLFloaterURLEntry::getMediaTypeCoro",
+            boost::bind(&LLFloaterURLEntry::getMediaTypeCoro, media_url, self->getHandle()));
 	}
 	else
 	{
@@ -239,6 +207,58 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
 	self->getChildView("media_entry")->setEnabled(false);
 }
 
+// static
+void LLFloaterURLEntry::getMediaTypeCoro(std::string url, LLHandle<LLFloater> parentHandle)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMediaTypeCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+    httpOpts->setHeadersOnly(true);
+
+    LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    LLFloaterURLEntry* floaterUrlEntry = (LLFloaterURLEntry*)parentHandle.get();
+    if (!floaterUrlEntry)
+    {
+        LL_WARNS() << "Could not get URL entry floater." << LL_ENDL;
+        return;
+    }
+
+    // Set empty type to none/none.  Empty string is reserved for legacy parcels
+    // which have no mime type set.
+    std::string resolvedMimeType = LLMIMETypes::getDefaultMimeType();
+
+    if (!status)
+    {
+        floaterUrlEntry->headerFetchComplete(status.getType(), resolvedMimeType);
+        return;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+
+    if (resultHeaders.has(HTTP_IN_HEADER_CONTENT_TYPE))
+    {
+        const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE];
+        std::string::size_type idx1 = mediaType.find_first_of(";");
+        std::string mimeType = mediaType.substr(0, idx1);
+        if (!mimeType.empty())
+        {
+            resolvedMimeType = mimeType;
+        }
+    }
+
+    floaterUrlEntry->headerFetchComplete(status.getType(), resolvedMimeType);
+
+}
+
 // static
 //-----------------------------------------------------------------------------
 // onBtnCancel()
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index bdd1ebe5921f5dbd01a48d694ab6c5a9e7c5ec57..20f4604907acceb12b84e2eb0b36906782841751 100755
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -29,6 +29,8 @@
 
 #include "llfloater.h"
 #include "llpanellandmedia.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLLineEditor;
 class LLComboBox;
@@ -56,7 +58,10 @@ class LLFloaterURLEntry : public LLFloater
 	static void		onBtnOK(void*);
 	static void		onBtnCancel(void*);
 	static void		onBtnClear(void*);
-	bool		callback_clear_url_list(const LLSD& notification, const LLSD& response);
+	bool		    callback_clear_url_list(const LLSD& notification, const LLSD& response);
+
+    static void     getMediaTypeCoro(std::string url, LLHandle<LLFloater> parentHandle);
+
 };
 
 #endif  // LL_LLFLOATERURLENTRY_H
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 86f9da63185fc8662c4c734686e035423f8989d4..4559132aebbe771296b5c29d664830ce38f3092f 100755
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -41,7 +41,6 @@
 #include "llui.h"
 #include "message.h"
 #include "roles_constants.h"
-#include "llhttpclient.h"
 #include "lltransactiontypes.h"
 #include "llstatusbar.h"
 #include "lleconomy.h"
@@ -53,6 +52,7 @@
 #include "lltrans.h"
 #include "llviewerregion.h"
 #include <boost/regex.hpp>
+#include "llcorehttputil.h"
 
 #if LL_MSVC
 #pragma warning(push)   
@@ -768,9 +768,9 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
 // LLGroupMgr
 //
 
-LLGroupMgr::LLGroupMgr()
+LLGroupMgr::LLGroupMgr():
+    mMemberRequestInFlight(false)
 {
-	mLastGroupMembersRequestFrame = 0;
 }
 
 LLGroupMgr::~LLGroupMgr()
@@ -1861,49 +1861,94 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
 	group_datap->mMemberVersion.generate();
 }
 
-
-// Responder class for capability group management
-class GroupBanDataResponder : public LLHTTPClient::Responder
+void LLGroupMgr::getGroupBanRequestCoro(std::string url, LLUUID groupId)
 {
-public:
-	GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh=false);
-	virtual ~GroupBanDataResponder() {}
-	virtual void httpSuccess();
-	virtual void httpFailure();
-private:
-	LLUUID mGroupID;
-	BOOL mForceRefresh;
-};
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-GroupBanDataResponder::GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh) :
-	mGroupID(gropup_id),
-	mForceRefresh(force_refresh)
-{}
+    std::string finalUrl = url + "?group_id=" + groupId.asString();
 
-void GroupBanDataResponder::httpFailure()
-{
-	LL_WARNS("GrpMgr") << "Error receiving group member data [status:" 
-		<< mStatus << "]: " << mContent << LL_ENDL;
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("GrpMgr") << "Error receiving group member data " << LL_ENDL;
+        return;
+    }
+
+    if (result.has("ban_list"))
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        // group ban data received
+        processGroupBanRequest(result);
+    }
 }
 
-void GroupBanDataResponder::httpSuccess()
+void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID groupId,
+    U32 action, uuid_vec_t banList, bool update)
 {
-	if (mContent.has("ban_list"))
-	{
-		// group ban data received
-		LLGroupMgr::processGroupBanRequest(mContent);
-	}
-	else if (mForceRefresh)
-	{
-		// no ban data received, refreshing data after successful operation 
-		LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions);
+
+    httpOptions->setFollowRedirects(false);
+
+    httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+
+
+    std::string finalUrl = url + "?group_id=" + groupId.asString();
+
+    LLSD postData = LLSD::emptyMap();
+    postData["ban_action"] = (LLSD::Integer)action;
+    // Add our list of potential banned residents to the list
+    postData["ban_ids"] = LLSD::emptyArray();
+    LLSD banEntry;
+
+    uuid_vec_t::const_iterator it = banList.begin();
+    for (; it != banList.end(); ++it)
+    {
+        banEntry = (*it);
+        postData["ban_ids"].append(banEntry);
+    }
+
+    LL_WARNS() << "post: " << ll_pretty_print_sd(postData) << LL_ENDL;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, finalUrl, postData, httpOptions, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("GrpMgr") << "Error posting group member data " << LL_ENDL;
+        return;
+    }
+
+    if (result.has("ban_list"))
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        // group ban data received
+        processGroupBanRequest(result);
+    }
+
+    if (update)
+    {
+        getGroupBanRequestCoro(url, groupId);
+    }
 }
 
 void LLGroupMgr::sendGroupBanRequest(	EBanRequestType request_type, 
 										const LLUUID& group_id, 
 										U32 ban_action, /* = BAN_NO_ACTION */
-										const std::vector<LLUUID> ban_list) /* = std::vector<LLUUID>() */
+										const std::vector<LLUUID> &ban_list) /* = std::vector<LLUUID>() */
 {
 	LLViewerRegion* currentRegion = gAgent.getRegion();
 	if(!currentRegion)
@@ -1925,37 +1970,27 @@ void LLGroupMgr::sendGroupBanRequest(	EBanRequestType request_type,
 	{
 		return;
 	}
-	cap_url += "?group_id=" + group_id.asString();
-
-	LLSD body = LLSD::emptyMap();
-	body["ban_action"]  = (LLSD::Integer)(ban_action & ~BAN_UPDATE);
-	// Add our list of potential banned residents to the list
-	body["ban_ids"]	= LLSD::emptyArray();
-	LLSD ban_entry;
 
-	uuid_vec_t::const_iterator iter = ban_list.begin();
-	for(;iter != ban_list.end(); ++iter)
-	{
-		ban_entry = (*iter);
-		body["ban_ids"].append(ban_entry);
-	}
+    U32 action = ban_action & ~BAN_UPDATE;
+    bool update = ((ban_action & BAN_UPDATE) == BAN_UPDATE);
 
-	LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(group_id, ban_action & BAN_UPDATE);
-	switch(request_type)
-	{
-	case REQUEST_GET:
-		LLHTTPClient::get(cap_url, grp_ban_responder);
-		break;
-	case REQUEST_POST:
-		LLHTTPClient::post(cap_url, body, grp_ban_responder);
-		break;
-	case REQUEST_PUT:
-	case REQUEST_DEL:
-		break;
-	}
+    switch (request_type)
+    {
+    case REQUEST_GET:
+        LLCoros::instance().launch("LLGroupMgr::getGroupBanRequestCoro",
+            boost::bind(&LLGroupMgr::getGroupBanRequestCoro, this, cap_url, group_id));
+        break;
+    case REQUEST_POST:
+        LLCoros::instance().launch("LLGroupMgr::postGroupBanRequestCoro",
+            boost::bind(&LLGroupMgr::postGroupBanRequestCoro, this, cap_url, group_id, 
+            action, ban_list, update));
+        break;
+    case REQUEST_PUT:
+    case REQUEST_DEL:
+        break;
+    }
 }
 
-
 void LLGroupMgr::processGroupBanRequest(const LLSD& content)
 {
 	// Did we get anything in content?
@@ -1993,45 +2028,42 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content)
 	LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);
 }
 
+void LLGroupMgr::groupMembersRequestCoro(std::string url, LLUUID groupId)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("groupMembersRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 
+    mMemberRequestInFlight = true;
 
-// Responder class for capability group management
-class GroupMemberDataResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(GroupMemberDataResponder);
-public:
-	GroupMemberDataResponder() {}
-	virtual ~GroupMemberDataResponder() {}
+    LLSD postData = LLSD::emptyMap();
+    postData["group_id"] = groupId;
 
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-	LLSD mMemberData;
-};
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
 
-void GroupMemberDataResponder::httpFailure()
-{
-	LL_WARNS("GrpMgr") << "Error receiving group member data "
-		<< dumpResponse() << LL_ENDL;
-}
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-void GroupMemberDataResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	LLGroupMgr::processCapGroupMembersRequest(content);
-}
+    if (!status)
+    {
+        LL_WARNS("GrpMgr") << "Error receiving group member data " << LL_ENDL;
+        mMemberRequestInFlight = false;
+        return;
+    }
 
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    LLGroupMgr::processCapGroupMembersRequest(result);
+    mMemberRequestInFlight = false;
+}
 
-// static
 void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
 {
+    static U32 lastGroupMemberRequestFrame = 0;
+
 	// Have we requested the information already this frame?
-	if(mLastGroupMembersRequestFrame == gFrameCount)
+    if ((lastGroupMemberRequestFrame == gFrameCount) || (mMemberRequestInFlight))
 		return;
 	
 	LLViewerRegion* currentRegion = gAgent.getRegion();
@@ -2060,20 +2092,13 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
 		return;
 	}
 
-	// Post to our service.  Add a body containing the group_id.
-	LLSD body = LLSD::emptyMap();
-	body["group_id"]	= group_id;
+    lastGroupMemberRequestFrame = gFrameCount;
 
-	LLHTTPClient::ResponderPtr grp_data_responder = new GroupMemberDataResponder();
-	
-	// This could take a while to finish, timeout after 5 minutes.
-	LLHTTPClient::post(cap_url, body, grp_data_responder, LLSD(), 300);
-
-	mLastGroupMembersRequestFrame = gFrameCount;
+    LLCoros::instance().launch("LLGroupMgr::groupMembersRequestCoro",
+        boost::bind(&LLGroupMgr::groupMembersRequestCoro, this, cap_url, group_id));
 }
 
 
-// static
 void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 {
 	// Did we get anything in content?
@@ -2090,7 +2115,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 	
 	LLUUID group_id = content["group_id"].asUUID();
 
-	LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
+	LLGroupMgrGroupData* group_datap = getGroupData(group_id);
 	if(!group_datap)
 	{
 		LL_WARNS("GrpMgr") << "Received incorrect, possibly stale, group or request id" << LL_ENDL;
@@ -2184,7 +2209,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 	// TODO:
 	// Refactor to reduce multiple calls for data we already have.
 	if(group_datap->mTitles.size() < 1)
-		LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
+		sendGroupTitlesRequest(group_id);
 
 
 	group_datap->mMemberDataComplete = true;
@@ -2193,11 +2218,11 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
 	if (group_datap->mPendingRoleMemberRequest || !group_datap->mRoleMemberDataComplete)
 	{
 		group_datap->mPendingRoleMemberRequest = false;
-		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id);
+		sendGroupRoleMembersRequest(group_id);
 	}
 
 	group_datap->mChanged = TRUE;
-	LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
+	notifyObservers(GC_MEMBER_DATA);
 
 }
 
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index 2e94e8d9a0d359484f6b50658f434ecbc8b828c0..fd0c2de854e47cf56464cb7baf6e1830a70fd01d 100755
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -32,6 +32,8 @@
 #include <vector>
 #include <string>
 #include <map>
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 // Forward Declarations
 class LLMessageSystem;
@@ -362,6 +364,7 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 		BAN_UPDATE		= 4
 	};
 
+
 public:
 	LLGroupMgr();
 	~LLGroupMgr();
@@ -396,15 +399,13 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 	static void sendGroupMemberEjects(const LLUUID& group_id,
 									  uuid_vec_t& member_ids);
 	
-	static void sendGroupBanRequest(EBanRequestType request_type, 
+	void sendGroupBanRequest(EBanRequestType request_type, 
 									const LLUUID& group_id,	
 									U32 ban_action = BAN_NO_ACTION,
-									const uuid_vec_t ban_list = uuid_vec_t());
+									const uuid_vec_t &ban_list = uuid_vec_t());
 
-	static void processGroupBanRequest(const LLSD& content);
 
 	void sendCapGroupMembersRequest(const LLUUID& group_id);
-	static void processCapGroupMembersRequest(const LLSD& content);
 
 	void cancelGroupRoleChanges(const LLUUID& group_id);
 
@@ -427,6 +428,14 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 	void clearGroupData(const LLUUID& group_id);
 
 private:
+    void groupMembersRequestCoro(std::string url, LLUUID groupId);
+    void processCapGroupMembersRequest(const LLSD& content);
+
+    void getGroupBanRequestCoro(std::string url, LLUUID groupId);
+    void postGroupBanRequestCoro(std::string url, LLUUID groupId, U32 action, uuid_vec_t banList, bool update);
+
+    static void processGroupBanRequest(const LLSD& content);
+
 	void notifyObservers(LLGroupChange gc);
 	void notifyObserver(const LLUUID& group_id, LLGroupChange gc);
 	void addGroup(LLGroupMgrGroupData* group_datap);
@@ -442,7 +451,7 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
 	typedef std::map<LLUUID,observer_set_t> observer_map_t;
 	observer_map_t mParticularObservers;
 
-	S32 mLastGroupMembersRequestFrame;
+    bool mMemberRequestInFlight;
 };
 
 
diff --git a/indra/newview/llhomelocationresponder.cpp b/indra/newview/llhomelocationresponder.cpp
deleted file mode 100755
index d0492bcdb438b0e190fcb982b07c9f9d7e1141ce..0000000000000000000000000000000000000000
--- a/indra/newview/llhomelocationresponder.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/** 
- * @file llhomelocationresponder.cpp
- * @author Meadhbh Hamrick
- * @brief Processes responses to the HomeLocation CapReq
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-/* File Inclusions */
-#include "llviewerprecompiledheaders.h"
-
-#include "llhomelocationresponder.h"
-#include "llsdutil.h"
-#include "llagent.h"
-#include "llviewerregion.h"
-
-void LLHomeLocationResponder::httpSuccess()
-{
-  const LLSD& content = getContent();
-  LLVector3 agent_pos;
-  bool      error = true;
-
-  do {
-
-    // was the call to /agent/<agent-id>/home-location successful?
-    // If not, we keep error set to true
-    if( ! content.has("success") )
-    {
-      break;
-    }
-
-    if( 0 != strncmp("true", content["success"].asString().c_str(), 4 ) )
-    {
-      break;
-    }
-
-    // did the simulator return a "justified" home location?
-    // If no, we keep error set to true
-    if( ! content.has( "HomeLocation" ) )
-    {
-      break;
-    }
-
-    if( ! content["HomeLocation"].has("LocationPos") )
-    {
-      break;
-    }
-
-    if( ! content["HomeLocation"]["LocationPos"].has("X") )
-    {
-      break;
-    }
-
-    agent_pos.mV[VX] = content["HomeLocation"]["LocationPos"]["X"].asInteger();
-
-    if( ! content["HomeLocation"]["LocationPos"].has("Y") )
-    {
-      break;
-    }
-
-    agent_pos.mV[VY] = content["HomeLocation"]["LocationPos"]["Y"].asInteger();
-
-    if( ! content["HomeLocation"]["LocationPos"].has("Z") )
-    {
-      break;
-    }
-
-    agent_pos.mV[VZ] = content["HomeLocation"]["LocationPos"]["Z"].asInteger();
-
-    error = false;
-  } while( 0 );
-
-  if( error )
-  {
-    failureResult(HTTP_INTERNAL_ERROR, "Invalid server response content", content);
-  }
-  else
-  {
-    LL_INFOS() << "setting home position" << LL_ENDL;
-
-    LLViewerRegion *viewer_region = gAgent.getRegion();
-    gAgent.setHomePosRegion( viewer_region->getHandle(), agent_pos );
-  }
-}
-
-void LLHomeLocationResponder::httpFailure()
-{
-  LL_WARNS() << dumpResponse() << LL_ENDL;
-}
diff --git a/indra/newview/llhomelocationresponder.h b/indra/newview/llhomelocationresponder.h
deleted file mode 100755
index adc6c8cb58109b11e5333c63b9dafbc0ae2ccb55..0000000000000000000000000000000000000000
--- a/indra/newview/llhomelocationresponder.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/** 
- * @file llhomelocationresponder.h
- * @author Meadhbh Hamrick
- * @brief Processes responses to the HomeLocation CapReq
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
- 
- /* Macro Definitions */
-#ifndef LL_LLHOMELOCATIONRESPONDER_H
-#define LL_LLHOMELOCATIONRESPONDER_H
-
-/* File Inclusions */
-#include "llhttpclient.h"
-
-/* Typedef, Enum, Class, Struct, etc. */
-class LLHomeLocationResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLHomeLocationResponder);
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-};
-
-#endif
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 2d4ce6c883a2c6bec31265b2fd3420ddbdf2ead2..6a2daeeb90882b1e683668d0749022beb111d44f 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -25,9 +25,23 @@
  */
 
 #include "llviewerprecompiledheaders.h"
-
 #include "llhttpretrypolicy.h"
 
+namespace
+{
+    // Moved from httpconstants.h... only used in this file.
+    bool isHttpServerErrorStatus(S32 status)
+    {
+        // Status 499 is sometimes used for re-interpreted status 2xx errors.
+        // Allow retry of these, since we don't have enough information in this
+        // context to know if this will always fail.
+        if (HTTP_INTERNAL_ERROR == status) return true;
+
+        // Check for status 5xx.
+        return((500 <= status) && (status < 600));
+    }
+}
+
 LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):
 	mMinDelay(min_delay),
 	mMaxDelay(max_delay),
@@ -56,7 +70,7 @@ bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header
 			&& getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time));
 }
 
-bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time)
+bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders::ptr_t &headers, F32& retry_header_time)
 {
 	if (headers)
 	{
@@ -85,9 +99,9 @@ void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
 void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
 {
 	F32 retry_header_time;
-	const LLCore::HttpHeaders *headers = response->getHeaders();
+	const LLCore::HttpHeaders::ptr_t headers = response->getHeaders();
 	bool has_retry_header_time = getRetryAfter(headers,retry_header_time);
-	onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time);
+	onFailureCommon(response->getStatus().getType(), has_retry_header_time, retry_header_time);
 }
 
 void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time)
@@ -140,3 +154,34 @@ bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
 	seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;
 	return mShouldRetry;
 }
+
+// Moved from httpconstants.  Only used by this file.
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+/*static*/
+bool LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
+{
+    // *TODO:  This needs testing!   Not in use yet.
+    // Examples of Retry-After headers:
+    // Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+    // Retry-After: 120
+
+    // Check for number of seconds version, first:
+    char* end = 0;
+    // Parse as double
+    double seconds = std::strtod(retry_after.c_str(), &end);
+    if (end != 0 && *end == 0)
+    {
+        // Successful parse
+        seconds_to_wait = (F32)seconds;
+        return true;
+    }
+
+    // Parse rfc1123 date.
+    time_t date = curl_getdate(retry_after.c_str(), NULL);
+    if (-1 == date) return false;
+
+    seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
+
+    return true;
+}
+
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index cf79e0b401b9948bcaf65480d33a3a82a51e6e78..af07b4afecbfc5065b8a3f9fabdd5788f29f5d1a 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -76,10 +76,12 @@ class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy
 	// virtual
 	bool shouldRetry(F32& seconds_to_wait) const;
 
+    static bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
 protected:
 	void init();
 	bool getRetryAfter(const LLSD& headers, F32& retry_header_time);
-	bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time);
+	bool getRetryAfter(const LLCore::HttpHeaders::ptr_t &headers, F32& retry_header_time);
 	void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time);
 
 private:
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index b8b6bdaa11747708ff29769ec528a4ad7a6cac14..53b97a58c5be24773cc2a3c518f37a3618db31b9 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -37,7 +37,6 @@
 #include "llrect.h"
 #include "llerror.h"
 #include "llbutton.h"
-#include "llhttpclient.h"
 #include "llsdutil_math.h"
 #include "llstring.h"
 #include "lltextutil.h"
@@ -69,6 +68,7 @@
 #include "llconversationlog.h"
 #include "message.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
 
 const static std::string ADHOC_NAME_SUFFIX(" Conference");
@@ -79,6 +79,10 @@ const static std::string NEARBY_P2P_BY_AGENT("nearby_P2P_by_agent");
 /** Timeout of outgoing session initialization (in seconds) */
 const static U32 SESSION_INITIALIZATION_TIMEOUT = 30;
 
+void startConfrenceCoro(std::string url, LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId, LLSD agents);
+void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType);
+void start_deprecated_conference_chat(const LLUUID& temp_session_id, const LLUUID& creator_id, const LLUUID& other_participant_id, const LLSD& agents_to_invite);
+
 std::string LLCallDialogManager::sPreviousSessionlName = "";
 LLIMModel::LLIMSession::SType LLCallDialogManager::sPreviousSessionType = LLIMModel::LLIMSession::P2P_SESSION;
 std::string LLCallDialogManager::sCurrentSessionlName = "";
@@ -110,7 +114,7 @@ void process_dnd_im(const LLSD& notification)
 {
     LLSD data = notification["substitutions"];
     LLUUID sessionID = data["SESSION_ID"].asUUID();
-	LLUUID fromID = data["FROM_ID"].asUUID();
+    LLUUID fromID = data["FROM_ID"].asUUID();
 
     //re-create the IM session if needed 
     //(when coming out of DND mode upon app restart)
@@ -131,12 +135,10 @@ void process_dnd_im(const LLSD& notification)
             fromID, 
             false, 
             false); //will need slight refactor to retrieve whether offline message or not (assume online for now)
-		}
-
-	notify_of_message(data, true);
     }
 
-
+    notify_of_message(data, true);
+}
 
 
 static void on_avatar_name_cache_toast(const LLUUID& agent_id,
@@ -387,6 +389,130 @@ void on_new_message(const LLSD& msg)
 	notify_of_message(msg, false);
 }
 
+void startConfrenceCoro(std::string url,
+    LLUUID tempSessionId, LLUUID creatorId, LLUUID otherParticipantId, LLSD agents)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD postData;
+    postData["method"] = "start conference";
+    postData["session-id"] = tempSessionId;
+    postData["params"] = agents;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("LLIMModel") << "Failed to start conference" << LL_ENDL;
+        //try an "old school" way.
+        // *TODO: What about other error status codes?  4xx 5xx?
+        if (status == LLCore::HttpStatus(HTTP_BAD_REQUEST))
+        {
+            start_deprecated_conference_chat(
+                tempSessionId,
+                creatorId,
+                otherParticipantId,
+                agents);
+        }
+
+        //else throw an error back to the client?
+        //in theory we should have just have these error strings
+        //etc. set up in this file as opposed to the IMMgr,
+        //but the error string were unneeded here previously
+        //and it is not worth the effort switching over all
+        //the possible different language translations
+    }
+}
+
+void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvitationType invitationType)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD postData;
+    postData["method"] = "accept invitation";
+    postData["session-id"] = sessionId;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!gIMMgr)
+    {
+        LL_WARNS("") << "Global IM Manager is NULL" << LL_ENDL;
+        return;
+    }
+
+    if (!status)
+    {
+        LL_WARNS("LLIMModel") << "Bad HTTP response in chatterBoxInvitationCoro" << LL_ENDL;
+        //throw something back to the viewer here?
+
+        gIMMgr->clearPendingAgentListUpdates(sessionId);
+        gIMMgr->clearPendingInvitation(sessionId);
+
+        if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+        {
+            static const std::string error_string("session_does_not_exist_error");
+            gIMMgr->showSessionStartError(error_string, sessionId);
+        }
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+    LLIMSpeakerMgr* speakerMgr = LLIMModel::getInstance()->getSpeakerManager(sessionId);
+    if (speakerMgr)
+    {
+        //we've accepted our invitation
+        //and received a list of agents that were
+        //currently in the session when the reply was sent
+        //to us.  Now, it is possible that there were some agents
+        //to slip in/out between when that message was sent to us
+        //and now.
+
+        //the agent list updates we've received have been
+        //accurate from the time we were added to the session
+        //but unfortunately, our base that we are receiving here
+        //may not be the most up to date.  It was accurate at
+        //some point in time though.
+        speakerMgr->setSpeakers(result);
+
+        //we now have our base of users in the session
+        //that was accurate at some point, but maybe not now
+        //so now we apply all of the updates we've received
+        //in case of race conditions
+        speakerMgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(sessionId));
+    }
+
+    if (LLIMMgr::INVITATION_TYPE_VOICE == invitationType)
+    {
+        gIMMgr->startCall(sessionId, LLVoiceChannel::INCOMING_CALL);
+    }
+
+    if ((invitationType == LLIMMgr::INVITATION_TYPE_VOICE
+        || invitationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
+        && LLIMModel::getInstance()->findIMSession(sessionId))
+    {
+        // TODO remove in 2010, for voice calls we do not open an IM window
+        //LLFloaterIMSession::show(mSessionID);
+    }
+
+    gIMMgr->clearPendingAgentListUpdates(sessionId);
+    gIMMgr->clearPendingInvitation(sessionId);
+
+}
+
+
 LLIMModel::LLIMModel() 
 {
 	addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1));
@@ -1465,54 +1591,6 @@ void start_deprecated_conference_chat(
 	delete[] bucket;
 }
 
-class LLStartConferenceChatResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLStartConferenceChatResponder);
-public:
-	LLStartConferenceChatResponder(
-		const LLUUID& temp_session_id,
-		const LLUUID& creator_id,
-		const LLUUID& other_participant_id,
-		const LLSD& agents_to_invite)
-	{
-		mTempSessionID = temp_session_id;
-		mCreatorID = creator_id;
-		mOtherParticipantID = other_participant_id;
-		mAgents = agents_to_invite;
-	}
-
-protected:
-	virtual void httpFailure()
-	{
-		//try an "old school" way.
-		// *TODO: What about other error status codes?  4xx 5xx?
-		if ( getStatus() == HTTP_BAD_REQUEST )
-		{
-			start_deprecated_conference_chat(
-				mTempSessionID,
-				mCreatorID,
-				mOtherParticipantID,
-				mAgents);
-		}
-
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-
-		//else throw an error back to the client?
-		//in theory we should have just have these error strings
-		//etc. set up in this file as opposed to the IMMgr,
-		//but the error string were unneeded here previously
-		//and it is not worth the effort switching over all
-		//the possible different language translations
-	}
-
-private:
-	LLUUID mTempSessionID;
-	LLUUID mCreatorID;
-	LLUUID mOtherParticipantID;
-
-	LLSD mAgents;
-};
-
 // Returns true if any messages were sent, false otherwise.
 // Is sort of equivalent to "does the server need to do anything?"
 bool LLIMModel::sendStartSession(
@@ -1549,20 +1627,10 @@ bool LLIMModel::sendStartSession(
 		{
 			std::string url = region->getCapability(
 				"ChatSessionRequest");
-			LLSD data;
-			data["method"] = "start conference";
-			data["session-id"] = temp_session_id;
-
-			data["params"] = agents;
 
-			LLHTTPClient::post(
-				url,
-				data,
-				new LLStartConferenceChatResponder(
-					temp_session_id,
-					gAgent.getID(),
-					other_participant_id,
-					data["params"]));
+            LLCoros::instance().launch("startConfrenceCoro",
+                boost::bind(&startConfrenceCoro, url,
+                temp_session_id, gAgent.getID(), other_participant_id, agents));
 		}
 		else
 		{
@@ -1580,97 +1648,6 @@ bool LLIMModel::sendStartSession(
 	return false;
 }
 
-//
-// Helper Functions
-//
-
-class LLViewerChatterBoxInvitationAcceptResponder :
-	public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLViewerChatterBoxInvitationAcceptResponder);
-public:
-	LLViewerChatterBoxInvitationAcceptResponder(
-		const LLUUID& session_id,
-		LLIMMgr::EInvitationType invitation_type)
-	{
-		mSessionID = session_id;
-		mInvitiationType = invitation_type;
-	}
-
-private:
-	void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		if ( gIMMgr)
-		{
-			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
-			if (speaker_mgr)
-			{
-				//we've accepted our invitation
-				//and received a list of agents that were
-				//currently in the session when the reply was sent
-				//to us.  Now, it is possible that there were some agents
-				//to slip in/out between when that message was sent to us
-				//and now.
-
-				//the agent list updates we've received have been
-				//accurate from the time we were added to the session
-				//but unfortunately, our base that we are receiving here
-				//may not be the most up to date.  It was accurate at
-				//some point in time though.
-				speaker_mgr->setSpeakers(content);
-
-				//we now have our base of users in the session
-				//that was accurate at some point, but maybe not now
-				//so now we apply all of the udpates we've received
-				//in case of race conditions
-				speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
-			}
-
-			if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)
-			{
-				gIMMgr->startCall(mSessionID, LLVoiceChannel::INCOMING_CALL);
-			}
-
-			if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE 
-				|| mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
-				&& LLIMModel::getInstance()->findIMSession(mSessionID))
-			{
-				// TODO remove in 2010, for voice calls we do not open an IM window
-				//LLFloaterIMSession::show(mSessionID);
-			}
-
-			gIMMgr->clearPendingAgentListUpdates(mSessionID);
-			gIMMgr->clearPendingInvitation(mSessionID);
-		}
-	}
-
-	void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-		//throw something back to the viewer here?
-		if ( gIMMgr )
-		{
-			gIMMgr->clearPendingAgentListUpdates(mSessionID);
-			gIMMgr->clearPendingInvitation(mSessionID);
-			if ( HTTP_NOT_FOUND == getStatus() )
-			{
-				static const std::string error_string("session_does_not_exist_error");
-				gIMMgr->showSessionStartError(error_string, mSessionID);
-			}
-		}
-	}
-
-private:
-	LLUUID mSessionID;
-	LLIMMgr::EInvitationType mInvitiationType;
-};
-
 
 // the other_participant_id is either an agent_id, a group_id, or an inventory
 // folder item_id (collection of calling cards)
@@ -2496,15 +2473,9 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
 
 			if (voice)
 			{
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						inv_type));
+                LLCoros::instance().launch("chatterBoxInvitationCoro",
+                    boost::bind(&chatterBoxInvitationCoro, url,
+                    session_id, inv_type));
 
 				// send notification message to the corresponding chat 
 				if (payload["notify_box_type"].asString() == "VoiceInviteGroup" || payload["notify_box_type"].asString() == "VoiceInviteAdHoc")
@@ -2539,10 +2510,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
 			LLSD data;
 			data["method"] = "decline invitation";
 			data["session-id"] = session_id;
-			LLHTTPClient::post(
-				url,
-				data,
-				NULL);
+
+            LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, data,
+                "Invitation declined", 
+                "Invitation decline failed.");
 		}
 	}
 
@@ -2589,15 +2560,9 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 				std::string url = gAgent.getRegion()->getCapability(
 					"ChatSessionRequest");
 
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						inv_type));
+                LLCoros::instance().launch("chatterBoxInvitationCoro",
+                    boost::bind(&chatterBoxInvitationCoro, url,
+                    session_id, inv_type));
 			}
 		}
 		break;
@@ -2627,10 +2592,9 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
 			LLSD data;
 			data["method"] = "decline invitation";
 			data["session-id"] = session_id;
-			LLHTTPClient::post(
-				url,
-				data,
-				NULL);				
+            LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, data, 
+                "Invitation declined.", 
+                "Invitation decline failed.");
 		}
 	}
 
@@ -3687,15 +3651,9 @@ class LLViewerChatterBoxInvitation : public LLHTTPNode
 
 			if ( url != "" )
 			{
-				LLSD data;
-				data["method"] = "accept invitation";
-				data["session-id"] = session_id;
-				LLHTTPClient::post(
-					url,
-					data,
-					new LLViewerChatterBoxInvitationAcceptResponder(
-						session_id,
-						LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
+                LLCoros::instance().launch("chatterBoxInvitationCoro",
+                    boost::bind(&chatterBoxInvitationCoro, url,
+                    session_id, LLIMMgr::INVITATION_TYPE_INSTANT_MESSAGE));
 			}
 		} //end if invitation has instant message
 		else if ( input["body"].has("voice") )
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index f92eff48458167219cdbd574f9587edad5d3bf69..41a8813acb2b4ac2cb933c673eca32735f017c52 100755
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,6 +34,9 @@
 #include "lllogchat.h"
 #include "llvoicechannel.h"
 
+#include "llcoros.h"
+#include "lleventcoro.h"
+
 class LLAvatarName;
 class LLFriendObserver;
 class LLCallDialogManager;	
@@ -292,6 +295,7 @@ class LLIMModel :  public LLSingleton<LLIMModel>
 	 * Add message to a list of message associated with session specified by session_id
 	 */
 	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+
 };
 
 class LLIMSessionObserver
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 605f71f412aa3c352d1b76979760da1e76576015..0c70b074bf4eb4cbea74625df32d4428677784d1 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -124,11 +124,6 @@ bool isRemoveAction(const std::string& action)
 	return ("take_off" == action || "detach" == action || "deactivate" == action);
 }
 
-bool isMarketplaceCopyAction(const std::string& action)
-{
-	return (("copy_to_outbox" == action) || ("move_to_outbox" == action));
-}
-
 bool isMarketplaceSendAction(const std::string& action)
 {
 	return ("send_to_marketplace" == action);
@@ -777,14 +772,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 			{
 				items.push_back(std::string("Marketplace Separator"));
 
-                if (gMenuHolder->getChild<LLView>("MerchantOutbox")->getVisible())
-                {
-                    items.push_back(std::string("Merchant Copy"));
-                    if (!canListOnOutboxNow())
-                    {
-                        disabled_items.push_back(std::string("Merchant Copy"));
-                    }
-                }
                 if (gMenuHolder->getChild<LLView>("MarketplaceListings")->getVisible())
                 {
                     items.push_back(std::string("Marketplace Copy"));
@@ -799,8 +786,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 		}
 	}
 
-	// Don't allow items to be pasted directly into the COF or the inbox/outbox
-	if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
+	// Don't allow items to be pasted directly into the COF or the inbox
+	if (!isCOFFolder() && !isInboxFolder())
 	{
 		items.push_back(std::string("Paste"));
 	}
@@ -838,10 +825,6 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}	
-	else if(isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
 	else
 	{
 		items.push_back(std::string("Share"));
@@ -942,19 +925,6 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
 		items.push_back(std::string("Open"));
 }
 
-void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags,
-												menuentry_vec_t &items,
-												menuentry_vec_t &disabled_items)
-{
-	items.push_back(std::string("Rename"));
-	items.push_back(std::string("Delete"));
-	
-	if ((flags & FIRST_SELECTED_ITEM) == 0)
-	{
-		disabled_items.push_back(std::string("Rename"));
-	}
-}
-
 void LLInvFVBridge::addMarketplaceContextMenuOptions(U32 flags,
 												menuentry_vec_t &items,
 												menuentry_vec_t &disabled_items)
@@ -1204,41 +1174,6 @@ BOOL LLInvFVBridge::isMarketplaceListingsFolder() const
 	return gInventory.isObjectDescendentOf(mUUID, folder_id);
 }
 
-BOOL LLInvFVBridge::isOutboxFolder() const
-{
-	const LLUUID outbox_id = getOutboxFolder();
-
-	if (outbox_id.isNull())
-	{
-		return FALSE;
-	}
-
-	return gInventory.isObjectDescendentOf(mUUID, outbox_id);
-}
-
-BOOL LLInvFVBridge::isOutboxFolderDirectParent() const
-{
-	BOOL outbox_is_parent = FALSE;
-	
-	const LLInventoryCategory *cat = gInventory.getCategory(mUUID);
-
-	if (cat)
-	{
-		const LLUUID outbox_id = getOutboxFolder();
-		
-		outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID()));
-	}
-	
-	return outbox_is_parent;
-}
-
-const LLUUID LLInvFVBridge::getOutboxFolder() const
-{
-	const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-
-	return outbox_id;
-}
-
 BOOL LLInvFVBridge::isItemPermissive() const
 {
 	return FALSE;
@@ -1495,56 +1430,6 @@ bool LLInvFVBridge::canListOnMarketplace() const
 	return true;
 }
 
-// *TODO : Suppress canListOnOutboxNow() once we deprecate Merchant Outbox completely
-bool LLInvFVBridge::canListOnOutboxNow() const
-{
-	bool can_list = true;
-
-	// Do not allow listing while import is in progress
-	if (LLMarketplaceInventoryImporter::instanceExists())
-	{
-		can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress();
-	}
-	
-	const LLInventoryObject* obj = getInventoryObject();
-	can_list &= (obj != NULL);
-
-	if (can_list)
-	{
-		const LLUUID& object_id = obj->getLinkedUUID();
-		can_list = object_id.notNull();
-
-		if (can_list)
-		{
-			LLFolderViewFolder * object_folderp =   mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;
-			if (object_folderp)
-			{
-				can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();
-			}
-		}
-		
-		if (can_list)
-		{
-			// Get outbox id
-			const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-			LLFolderViewItem * outbox_itemp =   mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;
-
-			if (outbox_itemp)
-			{
-				MASK mask = 0x0;
-				BOOL drop = FALSE;
-				EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
-				void * cargo_data = (void *) obj;
-				std::string tooltip_msg;
-				
-				can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
-			}
-		}
-	}
-	
-	return can_list;
-}
-
 bool LLInvFVBridge::canListOnMarketplaceNow() const
 {
 	bool can_list = true;
@@ -1714,16 +1599,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
 		folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();
 		return;
 	}
-	else if (isMarketplaceCopyAction(action))
-	{
-		LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL;
-
-		LLInventoryItem* itemp = model->getItem(mUUID);
-		if (!itemp) return;
-
-		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-		copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());
-	}
 	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
 	{
 		LLInventoryItem* itemp = model->getItem(mUUID);
@@ -2455,13 +2330,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 
 	const LLUUID &cat_id = inv_cat->getUUID();
 	const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
-	const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 	const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
     const LLUUID from_folder_uuid = inv_cat->getParentUUID();
 	
 	const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
-	const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); 
-	const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id);
 	const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
     const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id);
 
@@ -2602,9 +2474,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 			}
 		}
         
-		if (is_movable && (move_is_into_outbox || move_is_into_marketplacelistings))
+		if (is_movable && move_is_into_marketplacelistings)
 		{
-            const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+            const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
             LLViewerInventoryCategory * dest_folder = getCategory();
             S32 bundle_size = (drop ? 1 : LLToolDragAndDrop::instance().getCargoCount());
             is_movable = can_move_folder_to_marketplace(master_folder, dest_folder, inv_cat, tooltip_msg, bundle_size);
@@ -2713,10 +2585,6 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 				BOOL append = true;
 				LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
 			}
-			else if (move_is_into_outbox && !move_is_from_outbox)
-			{
-				copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId());
-			}
 			else if (move_is_into_marketplacelistings)
 			{
 				move_folder_to_marketplacelistings(inv_cat, mUUID);
@@ -2767,7 +2635,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	}
 	else if (LLToolDragAndDrop::SOURCE_WORLD == source)
 	{
-		if (move_is_into_outbox || move_is_into_marketplacelistings)
+		if (move_is_into_marketplacelistings)
 		{
 			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
@@ -2779,7 +2647,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
 	}
 	else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
 	{
-		if (move_is_into_outbox || move_is_into_marketplacelistings)
+		if (move_is_into_marketplacelistings)
 		{
 			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
@@ -3296,16 +3164,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		removeSystemFolder();
 	}
 #endif
-	else if (isMarketplaceCopyAction(action))
-	{
-		LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL;
-
-		LLInventoryCategory * cat = gInventory.getCategory(mUUID);
-		if (!cat) return;
-
-		const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-		copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());
-	}
 	else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
 	{
 		LLInventoryCategory * cat = gInventory.getCategory(mUUID);
@@ -3546,7 +3404,6 @@ void LLFolderBridge::perform_pasteFromClipboard()
 	if (model && isClipboardPasteable())
 	{
         const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
-		const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
         const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
 		const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
 		const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
@@ -3554,7 +3411,6 @@ void LLFolderBridge::perform_pasteFromClipboard()
 		const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
 		const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
 		const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
-		const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
         const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
 		const BOOL move_is_into_favorites = (mUUID == favorites_id);
 
@@ -3562,10 +3418,10 @@ void LLFolderBridge::perform_pasteFromClipboard()
 		LLClipboard::instance().pasteFromClipboard(objects);
         
         LLViewerInventoryCategory * dest_folder = getCategory();
-		if (move_is_into_outbox || move_is_into_marketplacelistings)
+		if (move_is_into_marketplacelistings)
 		{
             std::string error_msg;
-            const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+            const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
             int index = 0;
             for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)
             {
@@ -3744,17 +3600,15 @@ void LLFolderBridge::pasteLinkFromClipboard()
 	if(model)
 	{
 		const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
-		const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
         const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
 		const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
 
 		const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
 		const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
 		const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
-		const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
         const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
 
-		if (move_is_into_outbox || move_is_into_marketplacelistings)
+		if (move_is_into_marketplacelistings)
 		{
 			// Notify user of failure somehow -- play error sound?  modal dialog?
 			return;
@@ -3875,10 +3729,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		items.clear(); // clear any items that used to exist
 		addTrashContextMenuOptions(items, disabled_items);
 	}
-	else if(isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
 	else if(isAgentInventory()) // do not allow creating in library
 	{
 		LLViewerInventoryCategory *cat = getCategory();
@@ -3886,7 +3736,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		// Not sure what the right thing is to do here.
 		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
 		{
-			if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox
+			if (!isInboxFolder()) // don't allow creation in inbox
 			{
 				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
 				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
@@ -3948,7 +3798,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("Delete System Folder"));
 	}
 
-	if (!isOutboxFolder() && !isMarketplaceListingsFolder())
+	if (!isMarketplaceListingsFolder())
 	{
 		items.push_back(std::string("Share"));
 		if (!canShare())
@@ -3994,7 +3844,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&
 	if (trash_id == mUUID) return;
 	if (isItemInTrash()) return;
 	if (!isAgentInventory()) return;
-	if (isOutboxFolder()) return;
     
 	if (!isItemRemovable())
 	{
@@ -4588,7 +4437,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 	const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
 	const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
 	const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
-	const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
 	const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
 	const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
     const LLUUID from_folder_uuid = inv_item->getParentUUID();
@@ -4598,8 +4446,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 	const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
 	const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
 	const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
-	const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
-	const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);
     const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
     const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id);
 
@@ -4675,9 +4521,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		{
 			accept = can_move_to_landmarks(inv_item);
 		}
-		else if (user_confirm && (move_is_into_outbox || move_is_into_marketplacelistings))
+		else if (user_confirm && move_is_into_marketplacelistings)
 		{
-            const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+            const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
             LLViewerInventoryCategory * dest_folder = getCategory();
             accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex());
 		}
@@ -4762,19 +4608,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			{
 				dropToOutfit(inv_item, move_is_into_current_outfit);
 			}
-            // MERCHANT OUTBOX folder
-            // Move the item
-			else if (move_is_into_outbox)
-			{
-				if (move_is_from_outbox)
-				{
-					move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId());
-				}
-				else
-				{
-					copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
-				}
-			}
             // MARKETPLACE LISTINGS folder
             // Move the item
             else if (move_is_into_marketplacelistings)
@@ -4861,7 +4694,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		{
 			accept = FALSE;
 		}
-		else if (move_is_into_outbox || move_is_into_marketplacelistings)
+		else if (move_is_into_marketplacelistings)
 		{
 			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
@@ -4899,7 +4732,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 	}
 	else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
 	{
-		if (move_is_into_outbox || move_is_into_marketplacelistings)
+		if (move_is_into_marketplacelistings)
 		{
 			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
@@ -4933,7 +4766,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 		{
 			accept = TRUE;
 
-			if (move_is_into_outbox || move_is_into_marketplacelistings)
+			if (move_is_into_marketplacelistings)
 			{
 				tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 				accept = FALSE;
@@ -5102,10 +4935,6 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}	
-	else if(isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5175,11 +5004,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t items;
 	menuentry_vec_t disabled_items;
 
-	if (isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
-    else if (isMarketplaceListingsFolder())
+    if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
 		items.push_back(std::string("Properties"));
@@ -5256,11 +5081,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t disabled_items;
 
 	LL_DEBUGS() << "LLLandmarkBridge::buildContextMenu()" << LL_ENDL;
-	if(isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
-    else if (isMarketplaceListingsFolder())
+    if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
 		items.push_back(std::string("Properties"));
@@ -5554,10 +5375,6 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}	
-	else if(isOutboxFolder())
-	{
-		items.push_back(std::string("Delete"));
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5846,10 +5663,6 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}
-	else if(isOutboxFolder())
-	{
-		items.push_back(std::string("Delete"));
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5906,11 +5719,7 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	menuentry_vec_t disabled_items;
 
 	LL_DEBUGS() << "LLAnimationBridge::buildContextMenu()" << LL_ENDL;
-	if(isOutboxFolder())
-	{
-		items.push_back(std::string("Delete"));
-	}
-    else if (isMarketplaceListingsFolder())
+    if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
 		items.push_back(std::string("Properties"));
@@ -6171,10 +5980,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}	
-	else if(isOutboxFolder())
-	{
-		items.push_back(std::string("Delete"));
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -6399,10 +6204,6 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	{
 		addTrashContextMenuOptions(items, disabled_items);
 	}
-	else if(isOutboxFolder())
-	{
-		items.push_back(std::string("Delete"));
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -6705,10 +6506,6 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 
 		items.push_back(std::string("Restore Item"));
 	}
-	else if(isOutboxFolder())
-	{
-		addOutboxContextMenuOptions(flags, items, disabled_items);
-	}
     else if (isMarketplaceListingsFolder())
     {
 		addMarketplaceContextMenuOptions(flags, items, disabled_items);
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 7e7cf9c7dd5b1f87fbb6a8dd504ff0fbdb9dd6fa..30419ae9309014b83a60566947e8ea71946e3bd1 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -77,7 +77,6 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 
 	bool canShare() const;
 	bool canListOnMarketplace() const;
-	bool canListOnOutboxNow() const;
 	bool canListOnMarketplaceNow() const;
 
 	//--------------------------------------------------------------------
@@ -145,9 +144,6 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 	virtual void addDeleteContextMenuOptions(menuentry_vec_t &items,
 											 menuentry_vec_t &disabled_items);
 	virtual void addOpenRightClickMenuOption(menuentry_vec_t &items);
-	virtual void addOutboxContextMenuOptions(U32 flags,
-											 menuentry_vec_t &items,
-											 menuentry_vec_t &disabled_items);
 	virtual void addMarketplaceContextMenuOptions(U32 flags,
 											 menuentry_vec_t &items,
 											 menuentry_vec_t &disabled_items);
@@ -164,9 +160,7 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 	BOOL isCOFFolder() const;       // true if COF or descendant of
 	BOOL isInboxFolder() const;     // true if COF or descendant of   marketplace inbox
 
-	BOOL isOutboxFolderDirectParent() const;
 	BOOL isMarketplaceListingsFolder() const;     // true if descendant of Marketplace listings folder
-	const LLUUID getOutboxFolder() const;
 
 	virtual BOOL isItemPermissive() const;
 	static void changeItemParent(LLInventoryModel* model,
@@ -182,10 +176,6 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
     BOOL callback_cutToClipboard(const LLSD& notification, const LLSD& response);
     BOOL perform_cutToClipboard();
 
-public:
-	BOOL isOutboxFolder() const;    // true if COF or descendant of   marketplace outbox
-
-protected:
 	LLHandle<LLInventoryPanel> mInventoryPanel;
 	LLFolderView* mRoot;
 	const LLUUID mUUID;	// item id
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 990343c205d0d0a8d2339ea7da6c90f7fa56feeb..973bf5912517670d0023a7c640d12eef2e7c9a67 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -782,11 +782,6 @@ void reset_inventory_filter()
 	}
 }
 
-void open_outbox()
-{
-	LLFloaterReg::showInstance("outbox");
-}
-
 void open_marketplace_listings()
 {
 	LLFloaterReg::showInstance("marketplace_listings");
@@ -808,157 +803,6 @@ LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId)
 	return created_folder_id;
 }
 
-void move_to_outbox_cb_action(const LLSD& payload)
-{
-	LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
-	LLUUID dest_folder_id = payload["dest_folder_id"].asUUID();
-
-	if (viitem)
-	{	
-		// when moving item directly into outbox create folder with that name
-		if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
-		{
-			dest_folder_id = create_folder_for_item(viitem, dest_folder_id);
-		}
-
-		LLUUID parent = viitem->getParentUUID();
-
-		gInventory.changeItemParent(
-			viitem,
-			dest_folder_id,
-			false);
-
-		LLUUID top_level_folder = payload["top_level_folder"].asUUID();
-
-		if (top_level_folder != LLUUID::null)
-		{
-			LLViewerInventoryCategory* category;
-
-			while (parent.notNull())
-			{
-				LLInventoryModel::cat_array_t* cat_array;
-				LLInventoryModel::item_array_t* item_array;
-				gInventory.getDirectDescendentsOf(parent,cat_array,item_array);
-
-				LLUUID next_parent;
-
-				category = gInventory.getCategory(parent);
-
-				if (!category) break;
-
-				next_parent = category->getParentUUID();
-
-				if (cat_array->empty() && item_array->empty())
-				{
-					gInventory.removeCategory(parent);
-				}
-
-				if (parent == top_level_folder)
-				{
-					break;
-				}
-
-				parent = next_parent;
-			}
-		}
-
-		open_outbox();
-	}
-}
-
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
-{
-	// Collapse links directly to items/folders
-	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
-	LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
-	if (linked_category != NULL)
-	{
-		copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id);
-	}
-	else
-	{
-		LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
-		if (linked_item != NULL)
-		{
-			inv_item = (LLInventoryItem *) linked_item;
-		}
-		
-		// Check for copy permissions
-		if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
-		{
-			// when moving item directly into outbox create folder with that name
-			if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
-			{
-				dest_folder = create_folder_for_item(inv_item, dest_folder);
-			}
-			
-			copy_inventory_item(gAgent.getID(),
-								inv_item->getPermissions().getOwner(),
-								inv_item->getUUID(),
-								dest_folder,
-								inv_item->getName(),
-								LLPointer<LLInventoryCallback>(NULL));
-
-			open_outbox();
-		}
-		else
-		{
-			LLSD payload;
-			payload["item_id"] = inv_item->getUUID();
-			payload["dest_folder_id"] = dest_folder;
-			payload["top_level_folder"] = top_level_folder;
-			payload["operation_id"] = operation_id;
-			
-			LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
-		}
-	}
-}
-
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id)
-{
-	// when moving item directly into outbox create folder with that name
-	if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
-	{
-		dest_folder = create_folder_for_item(inv_item, dest_folder);
-	}
-	
-	LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
-
-	gInventory.changeItemParent(
-					   viewer_inv_item,
-					   dest_folder,
-					   false);
-}
-
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id)
-{
-	LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
-	gInventory.notifyObservers();
-
-	LLInventoryModel::cat_array_t* cat_array;
-	LLInventoryModel::item_array_t* item_array;
-	gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array);
-
-	// copy the vector because otherwise the iterator won't be happy if we delete from it
-	LLInventoryModel::item_array_t item_array_copy = *item_array;
-
-	for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
-	{
-		LLInventoryItem* item = *iter;
-		copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id);
-	}
-
-	LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
-
-	for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
-	{
-		LLViewerInventoryCategory* category = *iter;
-		copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id);
-	}
-
-	open_outbox();
-}
-
 ///----------------------------------------------------------------------------
 // Marketplace functions
 //
@@ -975,7 +819,7 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
     {
         return -1;
     }
-    // If not a descendent of the marketplace listings root, then the nesting depth is -1 by definition
+    // If not a descendant of the marketplace listings root, then the nesting depth is -1 by definition
     if (!gInventory.isObjectDescendentOf(cur_uuid, marketplace_listings_uuid))
     {
         return -1;
@@ -1605,7 +1449,7 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa
 
 void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)
 {
-    llinfos << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message <<  llendl;
+    LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message <<  LL_ENDL;
 }
 
 // Make all relevant business logic checks on the marketplace listings starting with the folder as argument.
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 6ae8fd0f13182727a6a323fa9c3c88b11a9d66b9..8aa8370f91641b2ffa3b30affcb40a38b055a91c 100755
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -75,10 +75,6 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory*
 // Generates a string containing the path to the item specified by item_id.
 void append_path(const LLUUID& id, std::string& path);
 
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id);
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id);
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id);
-
 typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
 
 bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0bad4702e00b45fb5e73b6daacdcc1ffe03139ee..53a58aff4c5d87e626dcdf61897f1b7449c587b2 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -149,8 +149,8 @@ LLInventoryModel::LLInventoryModel()
 	mObservers(),
 	mHttpRequestFG(NULL),
 	mHttpRequestBG(NULL),
-	mHttpOptions(NULL),
-	mHttpHeaders(NULL),
+	mHttpOptions(),
+	mHttpHeaders(),
 	mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
 	mHttpPriorityFG(0),
 	mHttpPriorityBG(0),
@@ -179,16 +179,9 @@ void LLInventoryModel::cleanupInventory()
 	mObservers.clear();
 
 	// Run down HTTP transport
-	if (mHttpHeaders)
-	{
-		mHttpHeaders->release();
-		mHttpHeaders = NULL;
-	}
-	if (mHttpOptions)
-	{
-		mHttpOptions->release();
-		mHttpOptions = NULL;
-	}
+    mHttpHeaders.reset();
+    mHttpOptions.reset();
+
 	delete mHttpRequestFG;
 	mHttpRequestFG = NULL;
 	delete mHttpRequestBG;
@@ -525,59 +518,6 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp
 	return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID());
 }
 
-class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLCreateInventoryCategoryResponder);
-public:
-	LLCreateInventoryCategoryResponder(LLInventoryModel* model, 
-									   boost::optional<inventory_func_type> callback):
-		mModel(model),
-		mCallback(callback) 
-	{
-	}
-	
-protected:
-	virtual void httpFailure()
-	{
-		LL_WARNS(LOG_INV) << dumpResponse() << LL_ENDL;
-	}
-	
-	virtual void httpSuccess()
-	{
-		//Server has created folder.
-		const LLSD& content = getContent();
-		if (!content.isMap() || !content.has("folder_id"))
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		LLUUID category_id = content["folder_id"].asUUID();
-		
-		LL_DEBUGS(LOG_INV) << ll_pretty_print_sd(content) << LL_ENDL;
-		// Add the category to the internal representation
-		LLPointer<LLViewerInventoryCategory> cat =
-		new LLViewerInventoryCategory( category_id, 
-									  content["parent_id"].asUUID(),
-									  (LLFolderType::EType)content["type"].asInteger(),
-									  content["name"].asString(), 
-									  gAgent.getID() );
-		cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
-		cat->setDescendentCount(0);
-		LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
-		mModel->accountForUpdate(update);
-		mModel->updateCategory(cat);
-
-		if (mCallback)
-		{
-			mCallback.get()(category_id);
-		}
-	}
-	
-private:
-	boost::optional<inventory_func_type> mCallback;
-	LLInventoryModel* mModel;
-};
-
 // Convenience function to create a new category. You could call
 // updateCategory() with a newly generated UUID category, but this
 // version will take care of details like what the name should be
@@ -585,7 +525,7 @@ class LLCreateInventoryCategoryResponder : public LLHTTPClient::Responder
 LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 										   LLFolderType::EType preferred_type,
 										   const std::string& pname,
-										   boost::optional<inventory_func_type> callback)
+										   inventory_func_type callback)
 {
 	
 	LLUUID id;
@@ -617,7 +557,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 	if ( viewer_region )
 		url = viewer_region->getCapability("CreateInventoryCategory");
 	
-	if (!url.empty() && callback.get_ptr())
+	if (!url.empty() && callback)
 	{
 		//Let's use the new capability.
 		
@@ -631,11 +571,8 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 		request["payload"] = body;
 
 		LL_DEBUGS(LOG_INV) << "create category request: " << ll_pretty_print_sd(request) << LL_ENDL;
-		//		viewer_region->getCapAPI().post(request);
-		LLHTTPClient::post(
-			url,
-			body,
-			new LLCreateInventoryCategoryResponder(this, callback) );
+        LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro",
+            boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback));
 
 		return LLUUID::null;
 	}
@@ -664,6 +601,57 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
 	return id;
 }
 
+void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inventory_func_type callback)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("createNewCategoryCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    
+
+    httpOpts->setWantHeaders(true);
+
+    LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "HTTP failure attempting to create category." << LL_ENDL;
+        return;
+    }
+
+    if (!result.has("folder_id"))
+    {
+        LL_WARNS() << "Malformed response contents" << ll_pretty_print_sd(result) << LL_ENDL;
+        return;
+    }
+
+    LLUUID categoryId = result["folder_id"].asUUID();
+
+    // Add the category to the internal representation
+    LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId,
+        result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
+        result["name"].asString(), gAgent.getID());
+
+    cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL);
+    cat->setDescendentCount(0);
+    LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+    
+    accountForUpdate(update);
+    updateCategory(cat);
+
+    if (callback)
+    {
+        callback(categoryId);
+    }
+
+}
+
 // This is optimized for the case that we just want to know whether a
 // category has any immediate children meeting a condition, without
 // needing to recurse or build up any lists.
@@ -2442,11 +2430,11 @@ void LLInventoryModel::initHttpRequest()
 
 		mHttpRequestFG = new LLCore::HttpRequest;
 		mHttpRequestBG = new LLCore::HttpRequest;
-		mHttpOptions = new LLCore::HttpOptions;
+		mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 		mHttpOptions->setTransferTimeout(300);
 		mHttpOptions->setUseRetryAfter(true);
 		// mHttpOptions->setTrace(2);		// Do tracing of requests
-		mHttpHeaders = new LLCore::HttpHeaders;
+        mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 		mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
 		mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_INVENTORY);
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index ac336e347cca2f8e7ca7382e730e90a8aa243e8a..a74e3b69f48cf55bb6a1a34f4a072f45eebbd8b5 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -35,7 +35,6 @@
 #include "llassettype.h"
 #include "llfoldertype.h"
 #include "llframetimer.h"
-#include "llcurl.h"
 #include "lluuid.h"
 #include "llpermissionsflags.h"
 #include "llviewerinventory.h"
@@ -46,6 +45,8 @@
 #include "httpoptions.h"
 #include "httpheaders.h"
 #include "httphandler.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLInventoryObserver;
 class LLInventoryObject;
@@ -207,14 +208,14 @@ class LLInventoryModel
  **/
 
 	//--------------------------------------------------------------------
-	// Descendents
+	// Descendants
 	//--------------------------------------------------------------------
 public:
-	// Make sure we have the descendents in the structure.  Returns true
+	// Make sure we have the descendants in the structure.  Returns true
 	// if a fetch was performed.
 	bool fetchDescendentsOf(const LLUUID& folder_id) const;
 
-	// Return the direct descendents of the id provided.Set passed
+	// Return the direct descendants of the id provided.Set passed
 	// in values to NULL if the call fails.
 	//    NOTE: The array provided points straight into the guts of
 	//    this object, and should only be used for read operations, since
@@ -223,10 +224,10 @@ class LLInventoryModel
 								cat_array_t*& categories,
 								item_array_t*& items) const;
 
-	// Compute a hash of direct descendent names (for detecting child name changes)
+	// Compute a hash of direct descendant names (for detecting child name changes)
 	LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const;
 	
-	// Starting with the object specified, add its descendents to the
+	// Starting with the object specified, add its descendants to the
 	// array provided, but do not add the inventory object specified
 	// by id. There is no guaranteed order. 
 	//    NOTE: Neither array will be erased before adding objects to it. 
@@ -340,7 +341,7 @@ class LLInventoryModel
 	U32 updateItem(const LLViewerInventoryItem* item, U32 mask = 0);
 
 	// Change an existing item with the matching id or add
-	// the category. No notifcation will be sent to observers. This
+	// the category. No notification will be sent to observers. This
 	// method will only generate network traffic if the item had to be
 	// reparented.
 	//    NOTE: In usage, you will want to perform cache accounting
@@ -378,7 +379,7 @@ class LLInventoryModel
 								   bool update_parent_version = true,
 								   bool do_notify_observers = true);
 
-	// Update model after all descendents removed from server.
+	// Update model after all descendants removed from server.
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
 
 	// Update model after an existing item gets updated on server.
@@ -409,7 +410,7 @@ class LLInventoryModel
 	// Changes items order by insertion of the item identified by src_item_id
 	// before (or after) the item identified by dest_item_id. Both items must exist in items array.
 	// Sorting is stored after method is finished. Only src_item_id is moved before (or after) dest_item_id.
-	// The parameter "insert_before" controls on which side of dest_item_id src_item_id gets rensinserted.
+	// The parameter "insert_before" controls on which side of dest_item_id src_item_id gets reinserted.
 	static void updateItemsOrder(LLInventoryModel::item_array_t& items, 
 								 const LLUUID& src_item_id, 
 								 const LLUUID& dest_item_id,
@@ -433,7 +434,7 @@ class LLInventoryModel
 	LLUUID createNewCategory(const LLUUID& parent_id,
 							 LLFolderType::EType preferred_type,
 							 const std::string& name,
-							 boost::optional<inventory_func_type> callback = boost::optional<inventory_func_type>());
+							 inventory_func_type callback = NULL);
 protected:
 	// Internal methods that add inventory and make sure that all of
 	// the internal data structures are consistent. These methods
@@ -441,6 +442,8 @@ class LLInventoryModel
 	// instance will take over the memory management from there.
 	void addCategory(LLViewerInventoryCategory* category);
 	void addItem(LLViewerInventoryItem* item);
+
+    void createNewCategoryCoro(std::string url, LLSD postData, inventory_func_type callback);
 	
 /**                    Mutators
  **                                                                            **
@@ -567,8 +570,8 @@ class LLInventoryModel
 	// Usual plumbing for LLCore:: HTTP operations.
 	LLCore::HttpRequest *				mHttpRequestFG;
 	LLCore::HttpRequest *				mHttpRequestBG;
-	LLCore::HttpOptions *				mHttpOptions;
-	LLCore::HttpHeaders *				mHttpHeaders;
+	LLCore::HttpOptions::ptr_t			mHttpOptions;
+	LLCore::HttpHeaders::ptr_t			mHttpHeaders;
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;
 	LLCore::HttpRequest::priority_t		mHttpPriorityFG;
 	LLCore::HttpRequest::priority_t		mHttpPriorityBG;
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 5194cba891a854c7674b1042716e17f9ee38b1e1..02d378bc5171fc59d55404e0aeb7d0f384789f9b 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1437,16 +1437,20 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask )
 		// Open selected items if enter key hit on the inventory panel
 		if (mask == MASK_NONE)
 		{
-			//Don't allow attaching or opening items from Merchant Outbox
-			LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
-			if(folder_item)
-			{
-				LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
-				if(bridge && bridge->isOutboxFolder() && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
-				{
-					return handled;
-				}
-			}
+
+// @TODO$: Rider: This code is dead with Outbox, however should something similar be 
+//  done for VMM?
+//  
+// 			//Don't allow attaching or opening items from Merchant Outbox
+// 			LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
+// 			if(folder_item)
+// 			{
+// 				LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+// 				if(bridge && bridge->is() && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
+// 				{
+// 					return handled;
+// 				}
+// 			}
 
 			LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), "open");
 			handled = TRUE;
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index d5bfe1df4af2cff455d2dc567237f75b71194f08..e8e56ef0cda2e60c3adad7677cdc72af55f749b8 100755
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -30,7 +30,6 @@
 
 #include "llagent.h"
 #include "llbufferstream.h"
-#include "llhttpclient.h"
 #include "llinventoryfunctions.h"
 #include "llinventoryobserver.h"
 #include "llnotificationsutil.h"
@@ -42,609 +41,112 @@
 #include "llviewermedia.h"
 #include "llviewernetwork.h"
 #include "llviewerregion.h"
-
 #include "reader.h" // JSON
 #include "writer.h" // JSON
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llcorehttputil.h"
 
+#include "llsdutil.h"
 //
 // Helpers
 //
 
-static std::string getMarketplaceDomain()
-{
-	std::string domain = "secondlife.com";
-	
-	if (!LLGridManager::getInstance()->isInProductionGrid())
-	{
-		const std::string& grid_id = LLGridManager::getInstance()->getGridId();
-		const std::string& grid_id_lower = utf8str_tolower(grid_id);
-		
-		if (grid_id_lower == "damballah")
-		{
-			domain = "secondlife-staging.com";
-		}
-		else
-		{
-			domain = llformat("%s.lindenlab.com", grid_id_lower.c_str());
-		}
-	}
-	
-	return domain;
-}
-
-static std::string getMarketplaceURL(const std::string& urlStringName)
-{
-	LLStringUtil::format_map_t domain_arg;
-	domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
-	
-	std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
-	
-	return marketplace_url;
-}
-
-LLSD getMarketplaceStringSubstitutions()
-{
-	std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
-	std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
-	std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
-	std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
-	std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
-	
-	LLSD marketplace_sub_map;
-
-	marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
-	marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
-	marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
-	marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
-	marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
-	
-	return marketplace_sub_map;
-}
-
-// Get the version folder: if there is only one subfolder, we will use it as a version folder
-LLUUID getVersionFolderIfUnique(const LLUUID& folder_id)
-{
-    LLUUID version_id = LLUUID::null;
-	LLInventoryModel::cat_array_t* categories;
-	LLInventoryModel::item_array_t* items;
-	gInventory.getDirectDescendentsOf(folder_id, categories, items);
-    if (categories->size() == 1)
-    {
-        version_id = categories->begin()->get()->getUUID();
-    }
-    else
-    {
-        LLNotificationsUtil::add("AlertMerchantListingActivateRequired");
-    }
-    return version_id;
-}
+namespace {
 
-///////////////////////////////////////////////////////////////////////////////
-// SLM Responders
-void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
-{
-    LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << description << LL_ENDL;
-    if ((status == 422) && (description == "[\"You must have an English description to list the product\", \"You must choose a category for your product before it can be listed\", \"Listing could not change state.\", \"Price can't be blank\"]"))
-    {
-        // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing
-        LLNotificationsUtil::add("MerchantUnprocessableEntity");
-    }
-    else
+    static std::string getMarketplaceDomain()
     {
-        // Prompt the user with the warning (so they know why things are failing)
-        LLSD subs;
-        subs["[ERROR_REASON]"] = reason;
-        // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though.
-        subs["[ERROR_DESCRIPTION]"] = (description.length() <= 512 ? description : "");
-        LLNotificationsUtil::add("MerchantTransactionFailed", subs);
-    }
-}
-void log_SLM_infos(const std::string& request, U32 status, const std::string& body)
-{
-    if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
-    {
-        LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL;
-    }
-}
-void log_SLM_infos(const std::string& request, const std::string& url, const std::string& body)
-{
-    if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
-    {
-		LL_INFOS("SLM") << "SLM API : Sending " << request << ". url : " << url << ", body : " << body << LL_ENDL;
-    }
-}
+        std::string domain = "secondlife.com";
 
-class LLSLMGetMerchantResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMGetMerchantResponder);
-public:
-	
-    LLSLMGetMerchantResponder() {}
-
-protected:
-    virtual void httpFailure()
-    {
-        if (HTTP_NOT_FOUND == getStatus())
-        {
-            log_SLM_infos("Get /merchant", getStatus(), "User is not a merchant");
-            LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT);
-        }
-        else if (HTTP_SERVICE_UNAVAILABLE == getStatus())
+        if (!LLGridManager::getInstance()->isInProductionGrid())
         {
-            log_SLM_infos("Get /merchant", getStatus(), "Merchant is not migrated");
-            LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
-        }
-		else
-		{
-            log_SLM_warning("Get /merchant", getStatus(), getReason(), getContent().get("error_code"), getContent().get("error_description"));
-            LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
-		}
-    }
-    
-    virtual void httpSuccess()
-    {
-        log_SLM_infos("Get /merchant", getStatus(), "User is a merchant");
-        LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT);
-    }
-    
-};
+            const std::string& grid_id = LLGridManager::getInstance()->getGridId();
+            const std::string& grid_id_lower = utf8str_tolower(grid_id);
 
-class LLSLMGetListingsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMGetListingsResponder);
-public:
-	
-    LLSLMGetListingsResponder(const LLUUID& folder_id)
-    {
-        mExpectedFolderId = folder_id;
-    }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
-    {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-        
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-
-		if (!isGoodStatus())
-		{
-            log_SLM_warning("Get /listings", getStatus(), getReason(), "", body);
-            LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
-        {
-            log_SLM_warning("Get /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-        }
-        
-        log_SLM_infos("Get /listings", getStatus(), body);
-        
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
-        {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            bool is_listed = listing["is_listed"].asBool();
-            std::string edit_url = listing["edit_url"].asString();
-            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
-            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
-            int count = listing["inventory_info"]["count_on_hand"].asInt();
-            
-            LLUUID folder_id(folder_uuid_string);
-            LLUUID version_id(version_uuid_string);
-            if (folder_id.notNull())
+            if (grid_id_lower == "damballah")
             {
-                LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
+                domain = "secondlife-staging.com";
+            }
+            else
+            {
+                domain = llformat("%s.lindenlab.com", grid_id_lower.c_str());
             }
-            it++;
         }
-        
-        // Update all folders under the root
-        LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE);
-        update_marketplace_category(mExpectedFolderId, false);
-        gInventory.notifyObservers();        
-    }
-private:
-    LLUUID mExpectedFolderId;
-};
 
-class LLSLMCreateListingsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMCreateListingsResponder);
-public:
-	
-    LLSLMCreateListingsResponder(const LLUUID& folder_id)
-    {
-        mExpectedFolderId = folder_id;
+        return domain;
     }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
+
+    static std::string getMarketplaceURL(const std::string& urlStringName)
     {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-        
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-        
-		if (!isGoodStatus())
-		{
-            log_SLM_warning("Post /listings", getStatus(), getReason(), "", body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-        
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
-        {
-            log_SLM_warning("Post /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-        }
+        LLStringUtil::format_map_t domain_arg;
+        domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
 
-        log_SLM_infos("Post /listings", getStatus(), body);
+        std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
 
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
-        {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            bool is_listed = listing["is_listed"].asBool();
-            std::string edit_url = listing["edit_url"].asString();
-            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
-            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
-            int count = listing["inventory_info"]["count_on_hand"].asInt();
-            
-            LLUUID folder_id(folder_uuid_string);
-            LLUUID version_id(version_uuid_string);
-            LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
-            update_marketplace_category(folder_id, false);
-            gInventory.notifyObservers();
-            it++;
-        }
+        return marketplace_url;
     }
-private:
-    LLUUID mExpectedFolderId;
-};
 
-class LLSLMGetListingResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMGetListingResponder);
-public:
-	
-    LLSLMGetListingResponder(const LLUUID& folder_id)
-    {
-        mExpectedFolderId = folder_id;
-    }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
+    // Get the version folder: if there is only one subfolder, we will use it as a version folder
+    LLUUID getVersionFolderIfUnique(const LLUUID& folder_id)
     {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-        
-		if (!isGoodStatus())
-		{
-            if (getStatus() == 404)
-            {
-                // That listing does not exist -> delete its record from the local SLM data store
-                LLMarketplaceData::instance().deleteListing(mExpectedFolderId, false);
-            }
-            else
-            {
-                log_SLM_warning("Get /listing", getStatus(), getReason(), "", body);
-            }
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-        
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
+        LLUUID version_id = LLUUID::null;
+        LLInventoryModel::cat_array_t* categories;
+        LLInventoryModel::item_array_t* items;
+        gInventory.getDirectDescendentsOf(folder_id, categories, items);
+        if (categories->size() == 1)
         {
-            log_SLM_warning("Get /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
+            version_id = categories->begin()->get()->getUUID();
         }
-        
-        log_SLM_infos("Get /listing", getStatus(), body);
-        
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
+        else
         {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            bool is_listed = listing["is_listed"].asBool();
-            std::string edit_url = listing["edit_url"].asString();
-            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
-            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
-            int count = listing["inventory_info"]["count_on_hand"].asInt();
-            
-            LLUUID folder_id(folder_uuid_string);
-            LLUUID version_id(version_uuid_string);
-            
-            // Update that listing
-            LLMarketplaceData::instance().setListingID(folder_id, listing_id, false);
-            LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false);
-            LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false);
-            LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false);
-            LLMarketplaceData::instance().setCountOnHand(folder_id,count,false);
-            update_marketplace_category(folder_id, false);
-            gInventory.notifyObservers();
-            
-            it++;
+            LLNotificationsUtil::add("AlertMerchantListingActivateRequired");
         }
+        return version_id;
     }
-private:
-    LLUUID mExpectedFolderId;
-};
 
-class LLSLMUpdateListingsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMUpdateListingsResponder);
-public:
-	
-    LLSLMUpdateListingsResponder(const LLUUID& folder_id, bool expected_listed_state, const LLUUID& expected_version_id)
+    ///////////////////////////////////////////////////////////////////////////////
+    // SLM Reporters
+    void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
     {
-        mExpectedFolderId = folder_id;
-        mExpectedListedState = expected_listed_state;
-        mExpectedVersionUUID = expected_version_id;
-    }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
-    {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-        
-		if (!isGoodStatus())
-		{
-            log_SLM_warning("Put /listing", getStatus(), getReason(), "", body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-        
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
+        LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << description << LL_ENDL;
+        if ((status == 422) && (description == "[\"You must have an English description to list the product\", \"You must choose a category for your product before it can be listed\", \"Listing could not change state.\", \"Price can't be blank\"]"))
         {
-            log_SLM_warning("Put /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
+            // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing
+            LLNotificationsUtil::add("MerchantUnprocessableEntity");
         }
-        
-        log_SLM_infos("Put /listing", getStatus(), body);
-
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
+        else
         {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            bool is_listed = listing["is_listed"].asBool();
-            std::string edit_url = listing["edit_url"].asString();
-            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
-            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
-            int count = listing["inventory_info"]["count_on_hand"].asInt();
-            
-            LLUUID folder_id(folder_uuid_string);
-            LLUUID version_id(version_uuid_string);
-            
-            // Update that listing
-            LLMarketplaceData::instance().setListingID(folder_id, listing_id, false);
-            LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false);
-            LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false);
-            LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false);
-            LLMarketplaceData::instance().setCountOnHand(folder_id,count,false);
-            update_marketplace_category(folder_id, false);
-            gInventory.notifyObservers();
-            
-            // Show a notification alert if what we got is not what we expected
-            // (this actually doesn't result in an error status from the SLM API protocol)
-            if ((mExpectedListedState != is_listed) || (mExpectedVersionUUID != version_id))
-            {
-                LLSD subs;
-                subs["[URL]"] = edit_url;
-                LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs);
-            }
-            
-            it++;
+            // Prompt the user with the warning (so they know why things are failing)
+            LLSD subs;
+            subs["[ERROR_REASON]"] = reason;
+            // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though.
+            subs["[ERROR_DESCRIPTION]"] = (description.length() <= 512 ? description : "");
+            LLNotificationsUtil::add("MerchantTransactionFailed", subs);
         }
     }
-private:
-    LLUUID mExpectedFolderId;
-    bool mExpectedListedState;
-    LLUUID mExpectedVersionUUID;
-};
 
-class LLSLMAssociateListingsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMAssociateListingsResponder);
-public:
-	
-    LLSLMAssociateListingsResponder(const LLUUID& folder_id, const LLUUID& source_folder_id)
+    void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const LLSD& description)
     {
-        mExpectedFolderId = folder_id;
-        mSourceFolderId = source_folder_id;
+        log_SLM_warning(request, status, reason, code, std::string(ll_pretty_print_sd(description)));
     }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
+
+    void log_SLM_infos(const std::string& request, U32 status, const std::string& body)
     {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-        LLMarketplaceData::instance().setUpdating(mSourceFolderId,false);
-        
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-        
-		if (!isGoodStatus())
-		{
-            log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), "", body);
-            update_marketplace_category(mExpectedFolderId, false);
-            update_marketplace_category(mSourceFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-        
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
-        {
-            log_SLM_warning("Put /associate_inventory", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            update_marketplace_category(mExpectedFolderId, false);
-            update_marketplace_category(mSourceFolderId, false);
-            gInventory.notifyObservers();
-            return;
-        }
-        
-        log_SLM_infos("Put /associate_inventory", getStatus(), body);
-        
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
+        if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
         {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            bool is_listed = listing["is_listed"].asBool();
-            std::string edit_url = listing["edit_url"].asString();
-            std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
-            std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
-            int count = listing["inventory_info"]["count_on_hand"].asInt();
-           
-            LLUUID folder_id(folder_uuid_string);
-            LLUUID version_id(version_uuid_string);
-            
-            // Check that the listing ID is not already associated to some other record
-            LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id);
-            if (old_listing.notNull())
-            {
-                // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID)
-                LLMarketplaceData::instance().deleteListing(old_listing);
-            }
-            
-            // Add the new association
-            LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
-            update_marketplace_category(folder_id, false);
-            gInventory.notifyObservers();
-            
-            // The stock count needs to be updated with the new local count now
-            LLMarketplaceData::instance().updateCountOnHand(folder_id,1);
-
-            it++;
+            LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL;
         }
-        
-        // Always update the source folder so its widget updates
-        update_marketplace_category(mSourceFolderId, false);
     }
-private:
-    LLUUID mExpectedFolderId;   // This is the folder now associated with the id.
-    LLUUID mSourceFolderId;     // This is the folder initially associated with the id. Can be LLUUI::null
-};
 
-class LLSLMDeleteListingsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSLMDeleteListingsResponder);
-public:
-	
-    LLSLMDeleteListingsResponder(const LLUUID& folder_id)
+    void log_SLM_infos(const std::string& request, U32 status, const LLSD& body)
     {
-        mExpectedFolderId = folder_id;
-    }
-    
-    virtual void completedRaw(const LLChannelDescriptors& channels,
-                              const LLIOPipe::buffer_ptr_t& buffer)
-    {
-        LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-        
-        LLBufferStream istr(channels, buffer.get());
-        std::stringstream strstrm;
-        strstrm << istr.rdbuf();
-        const std::string body = strstrm.str();
-        
-		if (!isGoodStatus())
-		{
-            log_SLM_warning("Delete /listing", getStatus(), getReason(), "", body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-		}
-        
-        Json::Value root;
-        Json::Reader reader;
-        if (!reader.parse(body,root))
-        {
-            log_SLM_warning("Delete /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
-            update_marketplace_category(mExpectedFolderId, false);
-            gInventory.notifyObservers();
-            return;
-        }
-        
-        log_SLM_infos("Delete /listing", getStatus(), body);
-        
-        // Extract the info from the Json string
-        Json::ValueIterator it = root["listings"].begin();
-        
-        while (it != root["listings"].end())
-        {
-            Json::Value listing = *it;
-            
-            int listing_id = listing["id"].asInt();
-            LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
-            LLMarketplaceData::instance().deleteListing(folder_id);
-            
-            it++;
-        }
+        log_SLM_infos(request, status, std::string(ll_pretty_print_sd(body)));
     }
-private:
-    LLUUID mExpectedFolderId;
-};
 
-// SLM Responders End
-///////////////////////////////////////////////////////////////////////////////
+}
+
 
+#if 1
 namespace LLMarketplaceImport
 {
 	// Basic interface for this namespace
@@ -669,105 +171,133 @@ namespace LLMarketplaceImport
 	static S32 sImportResultStatus = 0;
 	static LLSD sImportResults = LLSD::emptyMap();
 
-	static LLTimer slmGetTimer;
-	static LLTimer slmPostTimer;
-
 	// Responders
-	
-	class LLImportPostResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(LLImportPostResponder);
-	public:
-		LLImportPostResponder() : LLCurl::Responder() {}
 
-	protected:
-		/* virtual */ void httpCompleted()
-		{
-			slmPostTimer.stop();
-
-			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-			{
-				LL_INFOS() << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] "
-						   << dumpResponse() << LL_ENDL;
-			}
-
-			S32 status = getStatus();
-			if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
-				(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
-				// MAINT-2301 : we determined we can safely ignore that error in that context
-				(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
-			{
-				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-				{
-					LL_INFOS() << " SLM POST : Ignoring time out status and treating it as success" << LL_ENDL;
-				}
-				status = MarketplaceErrorCodes::IMPORT_DONE;
-			}
-			
-			if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)
-			{
-				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-				{
-					LL_INFOS() << " SLM POST : Clearing marketplace cookie due to client or server error" << LL_ENDL;
-				}
-				sMarketplaceCookie.clear();
-			}
-
-			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
-			sImportPostPending = false;
-			sImportResultStatus = status;
-			sImportId = getContent();
-		}
-	};
-	
-	class LLImportGetResponder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(LLImportGetResponder);
-	public:
-		LLImportGetResponder() : LLCurl::Responder() {}
-		
-	protected:
-		/* virtual */ void httpCompleted()
-		{
-			const std::string& set_cookie_string = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-			
-			if (!set_cookie_string.empty())
-			{
-				sMarketplaceCookie = set_cookie_string;
-			}
-
-			slmGetTimer.stop();
-
-			if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-			{
-				LL_INFOS() << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] "
-						   << dumpResponse() << LL_ENDL;
-			}
-			
-            // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions
-            // ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initally empty
-			S32 status = getStatus();
-			if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) &&
-                (status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) &&
-                (status != MarketplaceErrorCodes::IMPORT_NOT_FOUND))
-			{
-				if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-				{
-					LL_INFOS() << " SLM GET clearing marketplace cookie due to client or server error" << LL_ENDL;
-				}
-				sMarketplaceCookie.clear();
-			}
-            else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST))
+    void marketplacePostCoro(std::string url)
+    {
+        LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+            httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("marketplacePostCoro", httpPolicy));
+        LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+        LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+        LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+        httpOpts->setWantHeaders(true);
+        httpOpts->setFollowRedirects(true);
+
+        httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+        httpHeaders->append(HTTP_OUT_HEADER_CONNECTION, "Keep-Alive");
+        httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sMarketplaceCookie);
+        httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_XML);
+        httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, LLViewerMedia::getCurrentUserAgent());
+
+        LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD(), httpOpts, httpHeaders);
+
+        LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+        S32 httpCode = status.getType();
+        if ((httpCode == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
+            (httpCode == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
+            // MAINT-2301 : we determined we can safely ignore that error in that context
+            (httpCode == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
+        {
+            if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
             {
-                LL_INFOS() << " SLM GET : Got error status = " << status << ", but marketplace cookie not cleared." << LL_ENDL;
+                LL_INFOS() << " SLM POST : Ignoring time out status and treating it as success" << LL_ENDL;
             }
+            httpCode = MarketplaceErrorCodes::IMPORT_DONE;
+        }
 
-			sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
-			sImportGetPending = false;
-			sImportResultStatus = status;
-			sImportResults = getContent();
-		}
-	};
+        if (httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)
+        {
+            if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+            {
+                LL_INFOS() << " SLM POST clearing marketplace cookie due to client or server error" << LL_ENDL;
+            }
+            sMarketplaceCookie.clear();
+        }
+
+        sImportInProgress = (httpCode == MarketplaceErrorCodes::IMPORT_DONE);
+        sImportPostPending = false;
+        sImportResultStatus = httpCode;
+
+        {
+            std::stringstream str;
+            LLSDSerialize::toPrettyXML(result, str);
+
+            LL_INFOS() << "Full results:\n" << str.str() << "\n" << LL_ENDL;
+        }
+
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        sImportId = result;
+
+    }
+
+    void marketplaceGetCoro(std::string url, bool buildHeaders)
+    {
+        LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+            httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("marketplaceGetCoro", httpPolicy));
+        LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+        LLCore::HttpHeaders::ptr_t httpHeaders; 
+        LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+        httpOpts->setWantHeaders(true);
+        httpOpts->setFollowRedirects(!sMarketplaceCookie.empty());
+
+        if (buildHeaders)
+        {
+            httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
+
+            httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+            httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sMarketplaceCookie);
+            httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
+            httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, LLViewerMedia::getCurrentUserAgent());
+        }
+        else
+        {
+            httpHeaders = LLViewerMedia::getHttpHeaders();
+        }
+
+        LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+        LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+        LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+
+        if (sMarketplaceCookie.empty() && resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE))
+        {
+            sMarketplaceCookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asString();
+        }
+
+        // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions
+        // ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initially empty
+        S32 httpCode = status.getType();
+        if ((httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) &&
+            (httpCode != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) &&
+            (httpCode != MarketplaceErrorCodes::IMPORT_NOT_FOUND))
+        {
+            if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
+            {
+                LL_INFOS() << " SLM GET clearing marketplace cookie due to client or server error" << LL_ENDL;
+            }
+            sMarketplaceCookie.clear();
+        }
+        else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (httpCode >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST))
+        {
+            LL_INFOS() << " SLM GET : Got error status = " << httpCode << ", but marketplace cookie not cleared." << LL_ENDL;
+        }
+
+        sImportInProgress = (httpCode == MarketplaceErrorCodes::IMPORT_PROCESSING);
+        sImportGetPending = false;
+        sImportResultStatus = httpCode;
+
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        sImportResults = result;
+
+
+    }
 
 	// Basic API
 
@@ -818,20 +348,10 @@ namespace LLMarketplaceImport
 		sImportGetPending = true;
 		
 		std::string url = getInventoryImportURL();
-		
-		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-		{
-            LL_INFOS() << " SLM GET: establishMarketplaceSessionCookie, LLHTTPClient::get, url = " << url << LL_ENDL;
-            LLSD headers = LLViewerMedia::getHeaders();
-            std::stringstream str;
-            LLSDSerialize::toPrettyXML(headers, str);
-            LL_INFOS() << " SLM GET: headers " << LL_ENDL;
-            LL_INFOS() << str.str() << LL_ENDL;
-		}
 
-		slmGetTimer.start();
-		LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
-		
+        LLCoros::instance().launch("marketplaceGetCoro",
+            boost::bind(&marketplaceGetCoro, url, false));
+
 		return true;
 	}
 	
@@ -848,26 +368,9 @@ namespace LLMarketplaceImport
 
 		url += sImportId.asString();
 
-		// Make the headers for the post
-		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
-		// *TODO: Why are we setting Content-Type for a GET request?
-		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
-		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
-		
-		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-		{
-            LL_INFOS() << " SLM GET: pollStatus, LLHTTPClient::get, url = " << url << LL_ENDL;
-            std::stringstream str;
-            LLSDSerialize::toPrettyXML(headers, str);
-            LL_INFOS() << " SLM GET: headers " << LL_ENDL;
-            LL_INFOS() << str.str() << LL_ENDL;
-		}
-
-		slmGetTimer.start();
-		LLHTTPClient::get(url, new LLImportGetResponder(), headers);
-		
+        LLCoros::instance().launch("marketplaceGetCoro",
+            boost::bind(&marketplaceGetCoro, url, true));
+        
 		return true;
 	}
 	
@@ -886,35 +389,17 @@ namespace LLMarketplaceImport
 
 		std::string url = getInventoryImportURL();
 		
-		// Make the headers for the post
-		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_OUT_HEADER_CONNECTION] = "Keep-Alive";
-		headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
-		headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
-		headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
-		
-		if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
-		{
-            LL_INFOS() << " SLM POST: triggerImport, LLHTTPClient::post, url = " << url << LL_ENDL;
-            std::stringstream str;
-            LLSDSerialize::toPrettyXML(headers, str);
-            LL_INFOS() << " SLM POST: headers " << LL_ENDL;
-            LL_INFOS() << str.str() << LL_ENDL;
-		}
+        LLCoros::instance().launch("marketplacePostCoro",
+            boost::bind(&marketplacePostCoro, url));
 
-		slmPostTimer.start();
-        LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
-		
 		return true;
 	}
 }
-
+#endif
 
 //
 // Interface class
 //
-
 static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f;
 
 //static
@@ -1212,6 +697,26 @@ LLMarketplaceData::~LLMarketplaceData()
 	gInventory.removeObserver(mInventoryObserver);
 }
 
+
+LLSD LLMarketplaceData::getMarketplaceStringSubstitutions()
+{
+    std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
+    std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
+    std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
+    std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
+    std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
+
+    LLSD marketplace_sub_map;
+
+    marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
+    marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
+    marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
+    marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
+    marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
+
+    return marketplace_sub_map;
+}
+
 void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb)
 {
 	if (mStatusUpdatedSignal == NULL)
@@ -1227,15 +732,60 @@ void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type&
     }
     else
     {
-        // Initiate SLM connection and set responder
-        std::string url = getSLMConnectURL("/merchant");
-        if (url != "")
+        mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING;
+
+        LLCoros::instance().launch("getMerchantStatus",
+            boost::bind(&LLMarketplaceData::getMerchantStatusCoro, this));
+    }
+}
+
+void LLMarketplaceData::getMerchantStatusCoro()
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setFollowRedirects(true);
+
+    std::string url = getSLMConnectURL("/merchant");
+    if (url.empty())
+    {
+        LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
+    }
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    { 
+        S32 httpCode = status.getType();
+
+        if (httpCode == HTTP_NOT_FOUND)
+        {
+            log_SLM_infos("Get /merchant", httpCode, std::string("User is not a merchant"));
+            setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT);
+        }
+        else if (httpCode == HTTP_SERVICE_UNAVAILABLE)
+        {
+            log_SLM_infos("Get /merchant", httpCode, std::string("Merchant is not migrated"));
+            setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
+        }
+        else
         {
-            mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING;
-            log_SLM_infos("LLHTTPClient::get", url, "");
-            LLHTTPClient::get(url, new LLSLMGetMerchantResponder(), LLSD());
+            std::string err_code = result["error_code"].asString();
+            std::string err_description = result["error_description"].asString();
+            log_SLM_warning("Get /merchant", httpCode, status.toString(), err_code, err_description);
+            setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
         }
+        return;
     }
+
+    log_SLM_infos("Get /merchant", status.getType(), std::string("User is a merchant"));
+    setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT);
 }
 
 void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot_type& cb)
@@ -1250,151 +800,434 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot
 // Get/Post/Put requests to the SLM Server using the SLM API
 void LLMarketplaceData::getSLMListings()
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
-    
-	// Send request
+    const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+    setUpdating(marketplaceFolderId, true);
+
+    LLCoros::instance().launch("getSLMListings",
+        boost::bind(&LLMarketplaceData::getSLMListingsCoro, this, marketplaceFolderId));
+}
+
+void LLMarketplaceData::getSLMListingsCoro(LLUUID folderId)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
+
     std::string url = getSLMConnectURL("/listings");
-    log_SLM_infos("LLHTTPClient::get", url, "");
-	const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
-    setUpdating(marketplacelistings_id,true);
-	LLHTTPClient::get(url, new LLSLMGetListingsResponder(marketplacelistings_id), headers);
+
+    LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, url, httpHeaders);
+
+    setUpdating(folderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        log_SLM_warning("Get /listings", status.getType(), status.toString(), "", result);
+        setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
+        update_marketplace_category(folderId, false);
+        gInventory.notifyObservers();
+        return;
+    }
+
+    log_SLM_infos("Get /listings", static_cast<U32>(status.getType()), result);
+
+    // Extract the info from the results
+    for (LLSD::array_iterator it = result["listings"].beginArray();
+            it != result["listings"].endArray(); ++it)
+    { 
+        LLSD listing = *it;
+
+        int listingId = listing["id"].asInteger();
+        bool isListed = listing["is_listed"].asBoolean();
+        std::string editUrl = listing["edit_url"].asString();
+        LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+        LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+        int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+        if (folderUuid.notNull())
+        {
+            addListing(folderUuid, listingId, versionUuid, isListed, editUrl, count);
+        }
+    }
+
+    // Update all folders under the root
+    setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE);
+    update_marketplace_category(folderId, false);
+    gInventory.notifyObservers();
 }
 
-void LLMarketplaceData::getSLMListing(S32 listing_id)
+void LLMarketplaceData::getSLMListing(S32 listingId)
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
-    
-	// Send request
-    std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
-    log_SLM_infos("LLHTTPClient::get", url, "");
-    LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
-    setUpdating(folder_id,true);
-	LLHTTPClient::get(url, new LLSLMGetListingResponder(folder_id), headers);
+    LLUUID folderId = getListingFolder(listingId);
+    setUpdating(folderId, true);
+
+    LLCoros::instance().launch("getSingleListingCoro",
+        boost::bind(&LLMarketplaceData::getSingleListingCoro, this, listingId, folderId));
+}
+
+void LLMarketplaceData::getSingleListingCoro(S32 listingId, LLUUID folderId)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
+
+    std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+
+    LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, url, httpHeaders);
+
+    setUpdating(folderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        if (status.getType() == HTTP_NOT_FOUND)
+        {
+            // That listing does not exist -> delete its record from the local SLM data store
+            deleteListing(folderId, false);
+        }
+        else
+        {
+            log_SLM_warning("Get /listing", status.getType(), status.toString(), "", result);
+        }
+
+        update_marketplace_category(folderId, false);
+        gInventory.notifyObservers();
+        return;
+    }
+
+    log_SLM_infos("Get /listings", static_cast<U32>(status.getType()), result);
+
+
+    // Extract the info from the results
+    for (LLSD::array_iterator it = result["listings"].beginArray();
+        it != result["listings"].endArray(); ++it)
+    {
+        LLSD listing = *it;
+
+        int resListingId = listing["id"].asInteger();
+        bool isListed = listing["is_listed"].asBoolean();
+        std::string editUrl = listing["edit_url"].asString();
+        LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+        LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+        int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+        // Update that listing
+        setListingID(folderUuid, resListingId, false);
+        setVersionFolderID(folderUuid, versionUuid, false);
+        setActivationState(folderUuid, isListed, false);
+        setListingURL(folderUuid, editUrl, false);
+        setCountOnHand(folderUuid, count, false);
+        update_marketplace_category(folderUuid, false);
+        gInventory.notifyObservers();
+    }
 }
 
 void LLMarketplaceData::createSLMListing(const LLUUID& folder_id, const LLUUID& version_id, S32 count)
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
-    
-    // Build the json message
-    Json::Value root;
-    Json::FastWriter writer;
-    
-    LLViewerInventoryCategory* category = gInventory.getCategory(folder_id);
-    root["listing"]["name"] = category->getName();
-    root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
-    root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
-    root["listing"]["inventory_info"]["count_on_hand"] = count;
-    
-    std::string json_str = writer.write(root);
-    
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = json_str.size();
-	U8 *data = new U8[size];
-	memcpy(data, (U8*)(json_str.c_str()), size);
-    
-	// Send request
-    std::string url = getSLMConnectURL("/listings");
-    log_SLM_infos("LLHTTPClient::postRaw", url, json_str);
-    setUpdating(folder_id,true);
-	LLHTTPClient::postRaw(url, data, size, new LLSLMCreateListingsResponder(folder_id), headers);
+    setUpdating(folder_id, true);
+    LLCoros::instance().launch("createSLMListingCoro",
+        boost::bind(&LLMarketplaceData::createSLMListingCoro, this, folder_id, version_id, count));
 }
 
-void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count)
+void LLMarketplaceData::createSLMListingCoro(LLUUID folderId, LLUUID versionId, S32 count)
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
 
-    Json::Value root;
-    Json::FastWriter writer;
+    LLViewerInventoryCategory* category = gInventory.getCategory(folderId);
+    LLSD invInfo;
+    invInfo["listing_folder_id"] = folderId;
+    invInfo["version_folder_id"] = versionId;
+    invInfo["count_on_hand"] = count;
+    LLSD listing;
+    listing["name"] = category->getName();
+    listing["inventory_info"] = invInfo;
+    LLSD postData;
+    postData["listing"] = listing;
 
-    // Note : auto unlist if the count is 0 (out of stock)
-    if (is_listed && (count == 0))
+    std::string url = getSLMConnectURL("/listings");
+
+    LLSD result = httpAdapter->postJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+    setUpdating(folderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
     {
-        is_listed = false;
-        LLNotificationsUtil::add("AlertMerchantStockFolderEmpty");
+        log_SLM_warning("Post /listings", status.getType(), status.toString(), "", result);
+        update_marketplace_category(folderId, false);
+        gInventory.notifyObservers();
+        return;
     }
     
-    // Note : we're assuming that sending unchanged info won't break anything server side...
-    root["listing"]["id"] = listing_id;
-    root["listing"]["is_listed"] = is_listed;
-    root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
-    root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
-    root["listing"]["inventory_info"]["count_on_hand"] = count;
-    
-    std::string json_str = writer.write(root);
-    
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = json_str.size();
-	U8 *data = new U8[size];
-	memcpy(data, (U8*)(json_str.c_str()), size);
+    log_SLM_infos("Post /listings", status.getType(), result);
+
+    // Extract the info from the results
+    for (LLSD::array_iterator it = result["listings"].beginArray();
+        it != result["listings"].endArray(); ++it)
+    {
+        LLSD listing = *it;
+
+        int listingId = listing["id"].asInteger();
+        bool isListed = listing["is_listed"].asBoolean();
+        std::string editUrl = listing["edit_url"].asString();
+        LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+        LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+        int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+        addListing(folderUuid, listingId, versionUuid, isListed, editUrl, count);
+        update_marketplace_category(folderUuid, false);
+        gInventory.notifyObservers();
+    }
+
+}
+
+void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count)
+{
+    setUpdating(folder_id, true);
+    LLCoros::instance().launch("updateSLMListingCoro",
+        boost::bind(&LLMarketplaceData::updateSLMListingCoro, this, folder_id, listing_id, version_id, is_listed, count));
+}
+
+void LLMarketplaceData::updateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, bool isListed, S32 count)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
     
-	// Send request
-    std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
-    log_SLM_infos("LLHTTPClient::putRaw", url, json_str);
-    setUpdating(folder_id,true);
-	LLHTTPClient::putRaw(url, data, size, new LLSLMUpdateListingsResponder(folder_id, is_listed, version_id), headers);
+    LLSD invInfo;
+    invInfo["listing_folder_id"] = folderId;
+    invInfo["version_folder_id"] = versionId;
+    invInfo["count_on_hand"] = count;
+    LLSD listing;
+    listing["inventory_info"] = invInfo;
+    listing["id"] = listingId;
+    listing["is_listed"] = isListed;
+    LLSD postData;
+    postData["listing"] = listing;
+
+    std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+    LLSD result = httpAdapter->putJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+    setUpdating(folderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        log_SLM_warning("Put /listing", status.getType(), status.toString(), "", result);
+        update_marketplace_category(folderId, false);
+        gInventory.notifyObservers();
+        return;
+    }
+
+    log_SLM_infos("Put /listing", status.getType(), result);
+
+    // Extract the info from the Json string
+    for (LLSD::array_iterator it = result["listings"].beginArray();
+        it != result["listings"].endArray(); ++it)
+    {
+        LLSD listing = *it;
+
+        int listing_id = listing["id"].asInteger();
+        bool is_listed = listing["is_listed"].asBoolean();
+        std::string edit_url = listing["edit_url"].asString();
+        LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+        LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+        int onHand = listing["inventory_info"]["count_on_hand"].asInteger();
+
+        // Update that listing
+        setListingID(folderUuid, listing_id, false);
+        setVersionFolderID(folderUuid, versionUuid, false);
+        setActivationState(folderUuid, is_listed, false);
+        setListingURL(folderUuid, edit_url, false);
+        setCountOnHand(folderUuid, onHand, false);
+        update_marketplace_category(folderUuid, false);
+        gInventory.notifyObservers();
+
+        // Show a notification alert if what we got is not what we expected
+        // (this actually doesn't result in an error status from the SLM API protocol)
+        if ((isListed != is_listed) || (versionId != versionUuid))
+        {
+            LLSD subs;
+            subs["[URL]"] = edit_url;
+            LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs);
+        }
+    }
+
 }
 
 void LLMarketplaceData::associateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, const LLUUID& source_folder_id)
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
-    
-    Json::Value root;
-    Json::FastWriter writer;
-    
-    // Note : we're assuming that sending unchanged info won't break anything server side...
-    root["listing"]["id"] = listing_id;
-    root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
-    root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
-    
-    std::string json_str = writer.write(root);
-    
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = json_str.size();
-	U8 *data = new U8[size];
-	memcpy(data, (U8*)(json_str.c_str()), size);
-    
-	// Send request
-    std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d",listing_id);
-    log_SLM_infos("LLHTTPClient::putRaw", url, json_str);
-    setUpdating(folder_id,true);
-    setUpdating(source_folder_id,true);
-	LLHTTPClient::putRaw(url, data, size, new LLSLMAssociateListingsResponder(folder_id,source_folder_id), headers);
+    setUpdating(folder_id, true);
+    setUpdating(source_folder_id, true);
+    LLCoros::instance().launch("associateSLMListingCoro",
+        boost::bind(&LLMarketplaceData::associateSLMListingCoro, this, folder_id, listing_id, version_id, source_folder_id));
 }
 
-void LLMarketplaceData::deleteSLMListing(S32 listing_id)
+void LLMarketplaceData::associateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, LLUUID sourceFolderId)
 {
-	LLSD headers = LLSD::emptyMap();
-	headers["Accept"] = "application/json";
-	headers["Content-Type"] = "application/json";
-        
-	// Send request
-    std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
-    log_SLM_infos("LLHTTPClient::del", url, "");
-    LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
-    setUpdating(folder_id,true);
-	LLHTTPClient::del(url, new LLSLMDeleteListingsResponder(folder_id), headers);
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
+
+    LLSD invInfo;
+    invInfo["listing_folder_id"] = folderId;
+    invInfo["version_folder_id"] = versionId;
+    LLSD listing;
+    listing["id"] = listingId;
+    listing["inventory_info"] = invInfo;
+    LLSD postData;
+    postData["listing"] = listing;
+
+    // Send request
+    std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d", listingId);
+
+    LLSD result = httpAdapter->putJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+    setUpdating(folderId, false);
+    setUpdating(sourceFolderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        log_SLM_warning("Put /associate_inventory", status.getType(), status.toString(), "", result);
+        update_marketplace_category(folderId, false);
+        update_marketplace_category(sourceFolderId, false);
+        gInventory.notifyObservers();
+        return;
+    }
+
+    log_SLM_infos("Put /associate_inventory", status.getType(), result);
+
+    for (LLSD::array_iterator it = result["listings"].beginArray();
+            it != result["listings"].endArray(); ++it)
+    {
+        LLSD listing = *it;
+
+        int listing_id = listing["id"].asInteger();
+        bool is_listed = listing["is_listed"].asBoolean();
+        std::string edit_url = listing["edit_url"].asString();
+        LLUUID folder_uuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+        LLUUID version_uuid = listing["inventory_info"]["version_folder_id"].asUUID();
+        int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+        // Check that the listing ID is not already associated to some other record
+        LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id);
+        if (old_listing.notNull())
+        {
+            // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID)
+            deleteListing(old_listing);
+        }
+
+        // Add the new association
+        addListing(folder_uuid, listing_id, version_uuid, is_listed, edit_url, count);
+        update_marketplace_category(folder_uuid, false);
+        gInventory.notifyObservers();
+
+        // The stock count needs to be updated with the new local count now
+        updateCountOnHand(folder_uuid, 1);
+    }
+
+    // Always update the source folder so its widget updates
+    update_marketplace_category(sourceFolderId, false);
+}
+
+void LLMarketplaceData::deleteSLMListing(S32 listingId)
+{
+    LLCoros::instance().launch("deleteSLMListingCoro",
+        boost::bind(&LLMarketplaceData::deleteSLMListingCoro, this, listingId));
+}
+
+void LLMarketplaceData::deleteSLMListingCoro(S32 listingId)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    httpHeaders->append("Accept", "application/json");
+    httpHeaders->append("Content-Type", "application/json");
+
+    std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+    LLUUID folderId = getListingFolder(listingId);
+
+    setUpdating(folderId, true);
+
+    LLSD result = httpAdapter->deleteJsonAndSuspend(httpRequest, url, httpHeaders);
+
+    setUpdating(folderId, false);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        log_SLM_warning("Delete /listing", status.getType(), status.toString(), "", result);
+        update_marketplace_category(folderId, false);
+        gInventory.notifyObservers();
+        return;
+    }
+
+    log_SLM_infos("Delete /listing", status.getType(), result);
+
+    for (LLSD::array_iterator it = result["listings"].beginArray(); 
+            it != result["listings"].endArray(); ++it)
+    {
+        LLSD listing = *it;
+
+        int listing_id = listing["id"].asInteger();
+        LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
+        deleteListing(folder_id);
+    }
+
 }
 
 std::string LLMarketplaceData::getSLMConnectURL(const std::string& route)
 {
-    std::string url("");
+    std::string url;
     LLViewerRegion *regionp = gAgent.getRegion();
     if (regionp)
     {
         // Get DirectDelivery cap
         url = regionp->getCapability("DirectDelivery");
-        if (url != "")
+        if (!url.empty())
         {
             url += route;
         }
@@ -1983,5 +1816,3 @@ bool LLMarketplaceData::setListingURL(const LLUUID& folder_id, const std::string
     return true;
 }
 
-
-
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index f8e7ed43647f61b456c456308b36227b18697f92..9d795c6ced836e1c1287382168d739efeb82b0a6 100755
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -37,8 +37,6 @@
 #include "llstring.h"
 
 
-LLSD getMarketplaceStringSubstitutions();
-
 
 namespace MarketplaceErrorCodes
 {
@@ -183,6 +181,8 @@ class LLSLMDeleteListingsResponder;
 class LLMarketplaceData
     : public LLSingleton<LLMarketplaceData>
 {
+    friend class LLSingleton < LLMarketplaceData > ;
+
 public:
 	friend class LLSLMGetMerchantResponder;
     friend class LLSLMGetListingsResponder;
@@ -192,9 +192,8 @@ class LLMarketplaceData
     friend class LLSLMAssociateListingsResponder;
     friend class LLSLMDeleteListingsResponder;
 
-	LLMarketplaceData();
-    virtual ~LLMarketplaceData();
-    
+    static LLSD getMarketplaceStringSubstitutions();
+
     // Public SLM API : Initialization and status
 	typedef boost::signals2::signal<void ()> status_updated_signal_t;
     void initializeSLM(const status_updated_signal_t::slot_type& cb);
@@ -241,8 +240,11 @@ class LLMarketplaceData
     // Used to decide when to run a validation on listing folders
     void setValidationWaiting(const LLUUID& folder_id, S32 count);
     void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);
-    
+
 private:
+    LLMarketplaceData();
+    virtual ~LLMarketplaceData();
+
     // Modify Marketplace data set  : each method returns true if the function succeeds, false if error
     // Used internally only by SLM Responders when data are received from the SLM Server
     bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count);
@@ -261,6 +263,14 @@ class LLMarketplaceData
     void deleteSLMListing(S32 listing_id);
     std::string getSLMConnectURL(const std::string& route);
 
+    void getMerchantStatusCoro();
+    void getSLMListingsCoro(LLUUID folderId);
+    void getSingleListingCoro(S32 listingId, LLUUID folderId);
+    void createSLMListingCoro(LLUUID folderId, LLUUID versionId, S32 count);
+    void updateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, bool isListed, S32 count);
+    void associateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, LLUUID sourceFolderId);
+    void deleteSLMListingCoro(S32 listingId);
+
     // Handling Marketplace connection and inventory connection
 	U32  mMarketPlaceStatus;
 	status_updated_signal_t* mStatusUpdatedSignal;
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index a1f6a01aa0d279934c071d8a2059b31639b4c4aa..1045def72ee0acc3088a3ae6bfaed63e076d37a3 100755
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -36,6 +36,9 @@
 #include "llviewerobjectlist.h"
 #include "llviewerregion.h"
 #include "llworld.h"
+#include "llhttpsdhandler.h"
+#include "httpcommon.h"
+#include "llcorehttputil.h"
 
 /**
  * Materials cap parameters
@@ -59,56 +62,51 @@
 #define MATERIALS_PUT_THROTTLE_SECS               1.f
 #define MATERIALS_PUT_MAX_ENTRIES                 50
 
-/**
- * LLMaterialsResponder helper class
- */
 
-class LLMaterialsResponder : public LLHTTPClient::Responder
+
+class LLMaterialHttpHandler : public LLHttpSDHandler
 {
-public:
-	typedef boost::function<void (bool, const LLSD&)> CallbackFunction;
+public: 
+	typedef boost::function<void(bool, const LLSD&)> CallbackFunction;
+	typedef boost::shared_ptr<LLMaterialHttpHandler> ptr_t;
+
+	LLMaterialHttpHandler(const std::string& method, CallbackFunction cback);
 
-	LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback);
-	virtual ~LLMaterialsResponder();
+	virtual ~LLMaterialHttpHandler();
 
-	virtual void httpSuccess();
-	virtual void httpFailure();
+protected:
+	virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+	virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
 
 private:
 	std::string      mMethod;
-	std::string      mCapabilityURL;
 	CallbackFunction mCallback;
 };
 
-LLMaterialsResponder::LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback)
-	: LLHTTPClient::Responder()
-	, mMethod(pMethod)
-	, mCapabilityURL(pCapabilityURL)
-	, mCallback(pCallback)
+LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, CallbackFunction cback):
+	LLHttpSDHandler(),
+	mMethod(method),
+	mCallback(cback)
 {
+
 }
 
-LLMaterialsResponder::~LLMaterialsResponder()
+LLMaterialHttpHandler::~LLMaterialHttpHandler()
 {
 }
 
-void LLMaterialsResponder::httpSuccess()
+void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
 {
-	const LLSD& pContent = getContent();
-
 	LL_DEBUGS("Materials") << LL_ENDL;
-	mCallback(true, pContent);
+	mCallback(true, content);
 }
 
-void LLMaterialsResponder::httpFailure()
+void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
 {
-	U32 pStatus = (U32) getStatus();
-	const std::string& pReason = getReason();
-	
 	LL_WARNS("Materials")
 		<< "\n--------------------------------------------------------------------------\n"
-		<< mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
-		<< "'\n  with url '" << mCapabilityURL	<< "' because " << pReason 
+		<< mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME
+		<< "'\n  with url '" << response->getRequestURL() << "' because " << status.toString()
 		<< "\n--------------------------------------------------------------------------"
 		<< LL_ENDL;
 
@@ -116,12 +114,35 @@ void LLMaterialsResponder::httpFailure()
 	mCallback(false, emptyResult);
 }
 
+
+
 /**
  * LLMaterialMgr class
  */
-
-LLMaterialMgr::LLMaterialMgr()
+LLMaterialMgr::LLMaterialMgr():
+	mGetQueue(),
+	mGetPending(),
+	mGetCallbacks(),
+	mGetTECallbacks(),
+	mGetAllQueue(),
+	mGetAllRequested(),
+	mGetAllPending(),
+	mGetAllCallbacks(),
+	mPutQueue(),
+	mMaterials(),
+	mHttpRequest(),
+	mHttpHeaders(),
+	mHttpOptions(),
+	mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+	mHttpPriority(0)
 {
+	LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+
+	mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+	mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
+	mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
+	mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_MATERIALS);
+
 	mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(LLMaterialID::null, LLMaterialPtr(NULL)));
 	gIdleCallbacks.addFunction(&LLMaterialMgr::onIdle, NULL);
 	LLWorld::instance().setRegionRemovedCallback(boost::bind(&LLMaterialMgr::onRegionRemoved, this, _1));
@@ -554,6 +575,8 @@ void LLMaterialMgr::onIdle(void*)
 	{
 		instancep->processPutQueue();
 	}
+
+	instancep->mHttpRequest->update(0L);
 }
 
 void LLMaterialMgr::processGetQueue()
@@ -629,10 +652,26 @@ void LLMaterialMgr::processGetQueue()
 		LLSD postData = LLSD::emptyMap();
 		postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
 
-		LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id));
-		LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials." 
+		LLMaterialHttpHandler * handler = 
+				new LLMaterialHttpHandler("POST",
+				boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
+				);
+
+		LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials."
 			<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
-		LLHTTPClient::post(capURL, postData, materialsResponder);
+
+		LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, 
+				mHttpPolicy, mHttpPriority, capURL, 
+				postData, mHttpOptions, mHttpHeaders, handler);
+
+		if (handle == LLCORE_HTTP_HANDLE_INVALID)
+		{
+			delete handler;
+			LLCore::HttpStatus status = mHttpRequest->getStatus();
+			LL_ERRS("Meterials") << "Failed to execute material POST. Status = " <<
+				status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+		}
+
 		regionp->resetMaterialsCapThrottle();
 	}
 }
@@ -667,8 +706,22 @@ void LLMaterialMgr::processGetAllQueue()
 		}
 
 		LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
-		LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion));
-		LLHTTPClient::get(capURL, materialsResponder);
+		LLMaterialHttpHandler *handler = 
+			new LLMaterialHttpHandler("GET",
+			boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)
+			);
+
+		LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority, capURL,
+				mHttpOptions, mHttpHeaders, handler);
+
+		if (handle == LLCORE_HTTP_HANDLE_INVALID)
+		{
+			delete handler;
+			LLCore::HttpStatus status = mHttpRequest->getStatus();
+			LL_ERRS("Meterials") << "Failed to execute material GET. Status = " <<
+				status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+		}
+
 		regionp->resetMaterialsCapThrottle();
 		mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
 		mGetAllQueue.erase(itRegion);	// Invalidates region_id
@@ -755,8 +808,24 @@ void LLMaterialMgr::processPutQueue()
 			putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
 
 			LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
-			LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2));
-			LLHTTPClient::put(capURL, putData, materialsResponder);
+
+			LLMaterialHttpHandler * handler =
+					new LLMaterialHttpHandler("PUT",
+					boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
+					);
+
+			LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(
+				mHttpRequest, mHttpPolicy, mHttpPriority, capURL,
+				putData, mHttpOptions, mHttpHeaders, handler);
+
+			if (handle == LLCORE_HTTP_HANDLE_INVALID)
+			{
+				delete handler;
+				LLCore::HttpStatus status = mHttpRequest->getStatus();
+				LL_ERRS("Meterials") << "Failed to execute material PUT. Status = " << 
+					status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+			}
+
 			regionp->resetMaterialsCapThrottle();
 		}
 		else
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index e83f1f4e01464f1d5912867dbc7e87b99fcb4405..ef202d24baf5d847a211d74d084521e10badfba8 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -30,6 +30,9 @@
 #include "llmaterial.h"
 #include "llmaterialid.h"
 #include "llsingleton.h"
+#include "httprequest.h"
+#include "httpheaders.h"
+#include "httpoptions.h"
 
 class LLViewerRegion;
 
@@ -56,7 +59,7 @@ class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
 	void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);
 	void remove(const LLUUID& object_id, const U8 te);
 
-protected:
+private:
 	void clearGetQueues(const LLUUID& region_id);
 	bool isGetPending(const LLUUID& region_id, const LLMaterialID& material_id) const;
 	bool isGetAllPending(const LLUUID& region_id) const;
@@ -72,16 +75,7 @@ class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
 	void onPutResponse(bool success, const LLSD& content);
 	void onRegionRemoved(LLViewerRegion* regionp);
 
-protected:
-	typedef std::set<LLMaterialID> material_queue_t;
-	typedef std::map<LLUUID, material_queue_t> get_queue_t;
-	get_queue_t        mGetQueue;
-	typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
-	typedef std::map<const pending_material_t, F64> get_pending_map_t;
-	get_pending_map_t  mGetPending;
-	typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
-	get_callback_map_t mGetCallbacks;
-
+private:
 	// struct for TE-specific material ID query
 	class TEMaterialPair
 	{
@@ -108,22 +102,37 @@ class LLMaterialMgr : public LLSingleton<LLMaterialMgr>
 		bool   operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
 	};
 
-	typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
-	get_callback_te_map_t mGetTECallbacks;
+	typedef std::set<LLMaterialID> material_queue_t;
+	typedef std::map<LLUUID, material_queue_t> get_queue_t;
+	typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
+	typedef std::map<const pending_material_t, F64> get_pending_map_t;
+	typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
+
 
+	typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
 	typedef std::set<LLUUID> getall_queue_t;
-	getall_queue_t        mGetAllQueue;
-	getall_queue_t        mGetAllRequested;
 	typedef std::map<LLUUID, F64> getall_pending_map_t;
-	getall_pending_map_t  mGetAllPending;
 	typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
-	getall_callback_map_t mGetAllCallbacks;
-
 	typedef std::map<U8, LLMaterial> facematerial_map_t;
 	typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
-	put_queue_t mPutQueue;
 
-	material_map_t mMaterials;
+	get_queue_t				mGetQueue;
+	get_pending_map_t		mGetPending;
+	get_callback_map_t		mGetCallbacks;
+
+	get_callback_te_map_t	mGetTECallbacks;
+	getall_queue_t			mGetAllQueue;
+	getall_queue_t			mGetAllRequested;
+	getall_pending_map_t	mGetAllPending;
+	getall_callback_map_t	mGetAllCallbacks;
+	put_queue_t				mPutQueue;
+	material_map_t			mMaterials;
+
+	LLCore::HttpRequest::ptr_t		mHttpRequest;
+	LLCore::HttpHeaders::ptr_t		mHttpHeaders;
+	LLCore::HttpOptions::ptr_t		mHttpOptions;
+	LLCore::HttpRequest::policy_t	mHttpPolicy;
+	LLCore::HttpRequest::priority_t	mHttpPriority;
 
 	U32 getMaxEntries(const LLViewerRegion* regionp);
 };
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 2fb9e60b29e957d6615e48c38518c5707222094b..bfd0700a2f4d501c86bd44ea62bdd85c208bcd12 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -33,6 +33,7 @@
 #pragma warning (disable:4702)
 #endif
 
+#include <algorithm>
 #include <boost/lexical_cast.hpp>
 
 #include "llhttpconstants.h"
@@ -40,6 +41,7 @@
 #include "llmediaentry.h"
 #include "lltextureentry.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
 //
 // When making a request
@@ -91,52 +93,74 @@ const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q);
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q);
 
-template <typename T>
-typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type)
+
+//=========================================================================
+/// Uniary Predicate for matching requests in collections by either the request
+/// or by UUID
+/// 
+class PredicateMatchRequest
 {
-	for(typename T::iterator iter = c.begin(); iter != c.end(); ++iter)
-	{
-		if(request->isMatch(*iter, match_type))
-		{
-			return iter;
-		}
-	}
-	
-	return c.end();
+public:
+    PredicateMatchRequest(const LLMediaDataClient::Request::ptr_t &request, LLMediaDataClient::Request::Type matchType = LLMediaDataClient::Request::ANY);
+    PredicateMatchRequest(const LLUUID &id, LLMediaDataClient::Request::Type matchType = LLMediaDataClient::Request::ANY);
+
+    PredicateMatchRequest(const PredicateMatchRequest &other);
+
+    bool operator()(const LLMediaDataClient::Request::ptr_t &test) const;
+
+private:
+    LLMediaDataClient::Request::ptr_t mRequest;
+    LLMediaDataClient::Request::Type  mMatchType;
+    LLUUID                            mId;
+};
+
+
+PredicateMatchRequest::PredicateMatchRequest(const LLMediaDataClient::Request::ptr_t &request, LLMediaDataClient::Request::Type matchType) :
+    mRequest(request),
+    mMatchType(matchType),
+    mId()
+{}
+    
+PredicateMatchRequest::PredicateMatchRequest(const LLUUID &id, LLMediaDataClient::Request::Type matchType) :
+    mRequest(),
+    mMatchType(matchType),
+    mId(id)
+{}
+
+PredicateMatchRequest::PredicateMatchRequest(const PredicateMatchRequest &other)
+{
+    mRequest = other.mRequest;
+    mMatchType = other.mMatchType;
+    mId = other.mId;
 }
 
-template <typename T>
-typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type)
+bool PredicateMatchRequest::operator()(const LLMediaDataClient::Request::ptr_t &test) const
 {
-	for(typename T::iterator iter = c.begin(); iter != c.end(); ++iter)
-	{
-		if(((*iter)->getID() == id) && ((match_type == LLMediaDataClient::Request::ANY) || (match_type == (*iter)->getType())))
-		{
-			return iter;
-		}
-	}
-	
-	return c.end();
+    if (mRequest)
+        return (mRequest->isMatch(test, mMatchType));
+    else if (!mId.isNull())
+        return ((test->getID() == mId) && ((mMatchType == LLMediaDataClient::Request::ANY) || (mMatchType == test->getType())));
+    return false;
 }
 
-// NOTE: remove_matching_requests will not work correctly for containers where deleting an element may invalidate iterators
-// to other elements in the container (such as std::vector).
-// If the implementation is changed to use a container with this property, this will need to be revisited.
+//=========================================================================
+/// 
 template <typename T>
-void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type)
+void mark_dead_and_remove_if(T &c, const PredicateMatchRequest &matchPred)
 {
-	for(typename T::iterator iter = c.begin(); iter != c.end();)
-	{
-		typename T::value_type i = *iter;
-		typename T::iterator next = iter;
-		next++;
-		if((i->getID() == id) && ((match_type == LLMediaDataClient::Request::ANY) || (match_type == i->getType())))
-		{
-			i->markDead();
-			c.erase(iter);
-		}
-		iter = next;
-	}
+    for (typename T::iterator it = c.begin(); it != c.end();)
+    {
+        if (matchPred(*it))
+        {
+            (*it)->markDead();
+            // *TDOO: When C++11 is in change the following line to: it = c.erase(it);
+            c.erase(it++);
+        }
+        else
+        {
+            ++it;
+        }
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -145,18 +169,20 @@ void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
-LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
-									 F32 retry_timer_delay,
-									 U32 max_retries,
-									 U32 max_sorted_queue_size,
-									 U32 max_round_robin_queue_size)
-	: mQueueTimerDelay(queue_timer_delay),
-	  mRetryTimerDelay(retry_timer_delay),
-	  mMaxNumRetries(max_retries),
-	  mMaxSortedQueueSize(max_sorted_queue_size),
-	  mMaxRoundRobinQueueSize(max_round_robin_queue_size),
-	  mQueueTimerIsRunning(false)
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay, F32 retry_timer_delay,  
+        U32 max_retries, U32 max_sorted_queue_size, U32 max_round_robin_queue_size):
+    mQueueTimerDelay(queue_timer_delay),
+    mRetryTimerDelay(retry_timer_delay),
+    mMaxNumRetries(max_retries),
+    mMaxSortedQueueSize(max_sorted_queue_size),
+    mMaxRoundRobinQueueSize(max_round_robin_queue_size),
+    mQueueTimerIsRunning(false),
+    mHttpRequest(new LLCore::HttpRequest()),
+    mHttpHeaders(new LLCore::HttpHeaders()),
+    mHttpOpts(new LLCore::HttpOptions()),
+    mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID)
 {
+    // *TODO: Look up real Policy ID
 }
 
 LLMediaDataClient::~LLMediaDataClient()
@@ -171,20 +197,23 @@ bool LLMediaDataClient::isEmpty() const
 
 bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)
 {
-	if(find_matching_request(mQueue, object->getID(), LLMediaDataClient::Request::ANY) != mQueue.end())
-		return true;
-	
-	if(find_matching_request(mUnQueuedRequests, object->getID(), LLMediaDataClient::Request::ANY) != mUnQueuedRequests.end())
-		return true;
-	
+    PredicateMatchRequest upred(object->getID());
+
+    if (std::find_if(mQueue.begin(), mQueue.end(), upred) != mQueue.end())
+        return true;
+    if (std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred) != mUnQueuedRequests.end())
+        return true;
+    
 	return false;
 }
 
 void LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
 {
 	LL_DEBUGS("LLMediaDataClient") << "removing requests matching ID " << object->getID() << LL_ENDL;
-	remove_matching_requests(mQueue, object->getID(), LLMediaDataClient::Request::ANY);
-	remove_matching_requests(mUnQueuedRequests, object->getID(), LLMediaDataClient::Request::ANY);
+    PredicateMatchRequest upred(object->getID());
+
+    mark_dead_and_remove_if(mQueue, upred);
+    mark_dead_and_remove_if(mUnQueuedRequests, upred);
 }
 
 void LLMediaDataClient::startQueueTimer() 
@@ -207,23 +236,24 @@ void LLMediaDataClient::stopQueueTimer()
 
 bool LLMediaDataClient::processQueueTimer()
 {
-	if(isEmpty())
+    if (isDoneProcessing())
 		return true;
 
 	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue size is:	  " << mQueue.size() << LL_ENDL;
 	LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is:	  " << mQueue << LL_ENDL;
 			
 	serviceQueue();
-	
+    serviceHttp();
+
 	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue size is:	  " << mQueue.size() << LL_ENDL;
 	LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is:	  " << mQueue << LL_ENDL;
 	
-	return isEmpty();
+    return isDoneProcessing();
 }
 
-LLMediaDataClient::request_ptr_t LLMediaDataClient::dequeue()
+LLMediaDataClient::Request::ptr_t LLMediaDataClient::dequeue()
 {
-	request_ptr_t request;
+	Request::ptr_t request;
 	request_queue_t *queue_p = getQueue();
 	
 	if (queue_p->empty())
@@ -242,20 +272,20 @@ LLMediaDataClient::request_ptr_t LLMediaDataClient::dequeue()
 		else
 		{
 			// Don't return this request -- it's not ready to be serviced.
-			request = NULL;
+            request.reset();
 		}
 	}
 
 	return request;
 }
 
-void LLMediaDataClient::pushBack(request_ptr_t request)
+void LLMediaDataClient::pushBack(Request::ptr_t request)
 {
 	request_queue_t *queue_p = getQueue();
 	queue_p->push_front(request);
 }
 
-void LLMediaDataClient::trackRequest(request_ptr_t request)
+void LLMediaDataClient::trackRequest(Request::ptr_t request)
 {
 	request_set_t::iterator iter = mUnQueuedRequests.find(request);
 	
@@ -269,7 +299,7 @@ void LLMediaDataClient::trackRequest(request_ptr_t request)
 	}
 }
 
-void LLMediaDataClient::stopTrackingRequest(request_ptr_t request)
+void LLMediaDataClient::stopTrackingRequest(Request::ptr_t request)
 {
 	request_set_t::iterator iter = mUnQueuedRequests.find(request);
 	
@@ -283,16 +313,22 @@ void LLMediaDataClient::stopTrackingRequest(request_ptr_t request)
 	}
 }
 
+bool LLMediaDataClient::isDoneProcessing() const
+{
+    return (isEmpty() && mUnQueuedRequests.empty());
+}
+
+
 void LLMediaDataClient::serviceQueue()
 {	
 	// Peel one off of the items from the queue and execute it
-	request_ptr_t request;
+	Request::ptr_t request;
 	
 	do
 	{
 		request = dequeue();
 
-		if(request.isNull())
+		if(!request)
 		{
 			// Queue is empty.
 			return;
@@ -317,7 +353,18 @@ void LLMediaDataClient::serviceQueue()
 		trackRequest(request);
 		
 		// and make the post
-		LLHTTPClient::post(url, sd_payload, request->createResponder());
+        LLHttpSDHandler *handler = request->createHandler();
+        LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0,
+            url, sd_payload, mHttpOpts, mHttpHeaders, handler);
+
+        if (handle == LLCORE_HTTP_HANDLE_INVALID)
+        {
+            // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers.  Requires change in LLCore::HTTP
+            delete handler;
+            LLCore::HttpStatus status = mHttpRequest->getStatus();
+            LL_WARNS("LLMediaDataClient") << "'" << url << "' request POST failed. Reason "
+                << status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL;
+        }
 	}
 	else 
 	{
@@ -332,13 +379,17 @@ void LLMediaDataClient::serviceQueue()
 		}
 		else
 		{
-			// This request has exceeded its maxumim retry count.  It will be dropped.
+			// This request has exceeded its maximum retry count.  It will be dropped.
 			LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << mMaxNumRetries << " tries, dropping request." << LL_ENDL; 
 		}
 
 	}
 }
 
+void LLMediaDataClient::serviceHttp()
+{
+    mHttpRequest->update(0);
+}
 
 // dump the queue
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q)
@@ -395,7 +446,7 @@ BOOL LLMediaDataClient::QueueTimer::tick()
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
-LLMediaDataClient::RetryTimer::RetryTimer(F32 time, request_ptr_t request)
+LLMediaDataClient::RetryTimer::RetryTimer(F32 time, Request::ptr_t request)
 : LLEventTimer(time), mRequest(request)
 {
 	mRequest->startTracking();
@@ -417,7 +468,7 @@ BOOL LLMediaDataClient::RetryTimer::tick()
 	}
 	
 	// Release the ref to the request.
-	mRequest = NULL;
+    mRequest.reset();
 
 	// Don't fire again
 	return TRUE;
@@ -490,7 +541,7 @@ void LLMediaDataClient::Request::reEnqueue()
 {
 	if(mMDC)
 	{
-		mMDC->enqueue(this);
+		mMDC->enqueue(shared_from_this());
 	}
 }
 
@@ -533,13 +584,13 @@ bool LLMediaDataClient::Request::isDead()
 void LLMediaDataClient::Request::startTracking() 
 { 
 	if(mMDC) 
-		mMDC->trackRequest(this); 
+        mMDC->trackRequest(shared_from_this());
 }
 
 void LLMediaDataClient::Request::stopTracking() 
 { 
 	if(mMDC) 
-		mMDC->stopTrackingRequest(this); 
+        mMDC->stopTrackingRequest(shared_from_this());
 }
 
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
@@ -551,79 +602,61 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
 	<< " #retries=" << r.getRetryCount();
 	return s;
 }
-			
-//////////////////////////////////////////////////////////////////////////////////////
-//
-// LLMediaDataClient::Responder
-//
-//////////////////////////////////////////////////////////////////////////////////////
 
-LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
-: mRequest(request)
+//========================================================================
+
+LLMediaDataClient::Handler::Handler(const Request::ptr_t &request):
+    mRequest(request)
 {
 }
 
-/*virtual*/
-void LLMediaDataClient::Responder::httpFailure()
+
+void LLMediaDataClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
 {
-	mRequest->stopTracking();
+    mRequest->stopTracking();
 
-	if(mRequest->isDead())
-	{
-		LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL;
-		return;
-	}
-	
-	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
-	{
-		F32 retry_timeout;
-#if 0
-		// *TODO: Honor server Retry-After header.
-		if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER)
-			|| !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout))
-#endif
-		{
-			retry_timeout = mRequest->getRetryTimerDelay();
-		}
-		
-		mRequest->incRetryCount();
-		
-		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) 
-		{
-			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
-			
-			// Start timer (instances are automagically tracked by
-			// InstanceTracker<> and LLEventTimer)
-			new RetryTimer(F32(retry_timeout/*secs*/), mRequest);
-		}
-		else 
-		{
-			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " 
-				<< mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
-		}
-	}
-	// *TODO: Redirect on 3xx status codes.
-	else 
-	{
-		LL_WARNS("LLMediaDataClient") << *mRequest << " http failure "
-				<< dumpResponse() << LL_ENDL;
-	}
+    if (mRequest->isDead())
+    {
+        LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL;
+        return;
+    }
+
+    LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << LL_ENDL;
 }
 
-/*virtual*/
-void LLMediaDataClient::Responder::httpSuccess()
+void LLMediaDataClient::Handler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
 {
-	mRequest->stopTracking();
+    mRequest->stopTracking();
 
-	if(mRequest->isDead())
-	{
-		LL_WARNS("LLMediaDataClient") << "dead request " << *mRequest << LL_ENDL;
-		return;
-	}
+    if (status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE))
+    {
+        F32 retry_timeout;
+
+        retry_timeout = mRequest->getRetryTimerDelay();
+
+        mRequest->incRetryCount();
+
+        if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) 
+        {
+            LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
 
-	LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " " << dumpResponse() << LL_ENDL;
+            // Start timer (instances are automagically tracked by
+            // InstanceTracker<> and LLEventTimer)
+            new RetryTimer(F32(retry_timeout/*secs*/), mRequest);
+        }
+        else 
+        {
+            LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " 
+                << mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+        }
+    }
+    else
+    {
+        LL_WARNS("LLMediaDataClient") << *mRequest << " HTTP failure " << LL_ENDL;
+    }
 }
 
+
 //////////////////////////////////////////////////////////////////////////////////////
 //
 // LLObjectMediaDataClient
@@ -634,7 +667,7 @@ void LLMediaDataClient::Responder::httpSuccess()
 void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object)
 {
 	// Create a get request and put it in the queue.
-	enqueue(new RequestGet(object, this));
+	enqueue(Request::ptr_t(new RequestGet(object, this)));
 }
 
 const char *LLObjectMediaDataClient::getCapabilityName() const 
@@ -678,14 +711,14 @@ void LLObjectMediaDataClient::sortQueue()
 }
 
 // static
-bool LLObjectMediaDataClient::compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2)
+bool LLObjectMediaDataClient::compareRequestScores(const Request::ptr_t &o1, const Request::ptr_t &o2)
 {
-	if (o2.isNull()) return true;
-	if (o1.isNull()) return false;
+	if (!o2) return true;
+	if (!o1) return false;
 	return ( o1->getScore() > o2->getScore() );
 }
 
-void LLObjectMediaDataClient::enqueue(Request *request)
+void LLObjectMediaDataClient::enqueue(Request::ptr_t request)
 {
 	if(request->isDead())
 	{
@@ -703,9 +736,10 @@ void LLObjectMediaDataClient::enqueue(Request *request)
 	{
 		// For GET requests that are not new, if a matching request is already in the round robin queue, 
 		// in flight, or being retried, leave it at its current position.
-		request_queue_t::iterator iter = find_matching_request(mRoundRobinQueue, request->getID(), Request::GET);
-		request_set_t::iterator iter2 = find_matching_request(mUnQueuedRequests, request->getID(), Request::GET);
-		
+        PredicateMatchRequest upred(request->getID(), Request::GET);
+        request_queue_t::iterator iter = std::find_if(mRoundRobinQueue.begin(), mRoundRobinQueue.end(), upred);
+        request_set_t::iterator iter2 = std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred);
+
 		if( (iter != mRoundRobinQueue.end()) || (iter2 != mUnQueuedRequests.end()) )
 		{
 			LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL;
@@ -718,9 +752,11 @@ void LLObjectMediaDataClient::enqueue(Request *request)
 	// IF the update will cause an object update message to be sent out at some point in the future, it probably should.
 	
 	// Remove any existing requests of this type for this object
-	remove_matching_requests(mQueue, request->getID(), request->getType());
-	remove_matching_requests(mRoundRobinQueue, request->getID(), request->getType());
-	remove_matching_requests(mUnQueuedRequests, request->getID(), request->getType());
+    PredicateMatchRequest upred(request->getID(), request->getType());
+
+    mark_dead_and_remove_if(mQueue, upred);
+    mark_dead_and_remove_if(mRoundRobinQueue, upred);
+    mark_dead_and_remove_if(mUnQueuedRequests, upred);
 
 	if (is_new)
 	{
@@ -749,7 +785,7 @@ void LLObjectMediaDataClient::enqueue(Request *request)
 	startQueueTimer();
 }
 
-bool LLObjectMediaDataClient::canServiceRequest(request_ptr_t request) 
+bool LLObjectMediaDataClient::canServiceRequest(Request::ptr_t request) 
 {
 	if(mCurrentQueueIsTheSortedQueue)
 	{
@@ -785,9 +821,9 @@ bool LLObjectMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &ob
 	if(LLMediaDataClient::isInQueue(object))
 		return true;
 
-	if(find_matching_request(mRoundRobinQueue, object->getID(), LLMediaDataClient::Request::ANY) != mRoundRobinQueue.end())
-		return true;
-	
+    if (std::find_if(mRoundRobinQueue.begin(), mRoundRobinQueue.end(), PredicateMatchRequest(object->getID())) != mRoundRobinQueue.end())
+        return true;
+
 	return false;
 }
 
@@ -796,12 +832,12 @@ void LLObjectMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr
 	// First, call parent impl.
 	LLMediaDataClient::removeFromQueue(object);
 	
-	remove_matching_requests(mRoundRobinQueue, object->getID(), LLMediaDataClient::Request::ANY);
+    mark_dead_and_remove_if(mRoundRobinQueue, PredicateMatchRequest(object->getID()));
 }
 
 bool LLObjectMediaDataClient::processQueueTimer()
 {
-	if(isEmpty())
+    if (isDoneProcessing())
 		return true;
 		
 	LL_DEBUGS("LLMediaDataClient") << "started, SORTED queue size is:	  " << mQueue.size() 
@@ -816,6 +852,7 @@ bool LLObjectMediaDataClient::processQueueTimer()
 	LL_DEBUGS("LLMediaDataClientQueue") << "after sort, SORTED queue is:	  " << mQueue << LL_ENDL;
 	
 	serviceQueue();
+    serviceHttp();
 
 	swapCurrentQueue();
 	
@@ -824,7 +861,7 @@ bool LLObjectMediaDataClient::processQueueTimer()
 	LL_DEBUGS("LLMediaDataClientQueue") << "    SORTED queue is:	  " << mQueue << LL_ENDL;
 	LL_DEBUGS("LLMediaDataClientQueue") << "    RR queue is:	  " << mRoundRobinQueue << LL_ENDL;
 	
-	return isEmpty();
+    return isDoneProcessing();
 }
 
 LLObjectMediaDataClient::RequestGet::RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc):
@@ -841,16 +878,16 @@ LLSD LLObjectMediaDataClient::RequestGet::getPayload() const
 	return result;
 }
 
-LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestGet::createResponder()
+LLHttpSDHandler *LLObjectMediaDataClient::RequestGet::createHandler()
 {
-	return new LLObjectMediaDataClient::Responder(this);
+	return new LLObjectMediaDataClient::Handler(shared_from_this());
 }
 
 
 void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
 {
 	// Create an update request and put it in the queue.
-	enqueue(new RequestUpdate(object, this));
+	enqueue(Request::ptr_t(new RequestUpdate(object, this)));
 }
 
 LLObjectMediaDataClient::RequestUpdate::RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc):
@@ -877,60 +914,58 @@ LLSD LLObjectMediaDataClient::RequestUpdate::getPayload() const
 	return result;
 }
 
-LLMediaDataClient::Responder *LLObjectMediaDataClient::RequestUpdate::createResponder()
+LLHttpSDHandler *LLObjectMediaDataClient::RequestUpdate::createHandler()
 {
 	// This just uses the base class's responder.
-	return new LLMediaDataClient::Responder(this);
+	return new LLMediaDataClient::Handler(shared_from_this());
 }
 
-
-/*virtual*/
-void LLObjectMediaDataClient::Responder::httpSuccess()
+void LLObjectMediaDataClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
 {
-	getRequest()->stopTracking();
+    LLMediaDataClient::Handler::onSuccess(response, content);
+
+    if (getRequest()->isDead())
+    {   // warning emitted from base method.
+        return;
+    }
+
+    if (!content.isMap())
+    {
+        onFailure(response, LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents"));
+        return;
+    }
+
+    // This responder is only used for GET requests, not UPDATE.
+    LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << LL_ENDL;
+
+    // Look for an error
+    if (content.has("error"))
+    {
+        const LLSD &error = content["error"];
+        LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << 
+            error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+
+        // XXX Warn user?
+    }
+    else 
+    {
+        // Check the data
+        const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
+        if (object_id != getRequest()->getObject()->getID()) 
+        {
+            // NOT good, wrong object id!!
+            LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
+            return;
+        }
+
+        // Otherwise, update with object media data
+        getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
+            content[LLTextureEntry::MEDIA_VERSION_KEY]);
+    }
 
-	if(getRequest()->isDead())
-	{
-		LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL;
-		return;
-	}
-
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-
-	// This responder is only used for GET requests, not UPDATE.
-	LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
-
-	// Look for an error
-	if (content.has("error"))
-	{
-		const LLSD &error = content["error"];
-		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" << 
-			error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
-		
-		// XXX Warn user?
-	}
-	else 
-	{
-		// Check the data
-		const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
-		if (object_id != getRequest()->getObject()->getID()) 
-		{
-			// NOT good, wrong object id!!
-			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
-			return;
-		}
-		
-		// Otherwise, update with object media data
-		getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
-														 content[LLTextureEntry::MEDIA_VERSION_KEY]);
-	}
 }
 
+
 //////////////////////////////////////////////////////////////////////////////////////
 //
 // LLObjectMediaNavigateClient
@@ -943,16 +978,18 @@ const char *LLObjectMediaNavigateClient::getCapabilityName() const
 	return "ObjectMediaNavigate";
 }
 
-void LLObjectMediaNavigateClient::enqueue(Request *request)
+void LLObjectMediaNavigateClient::enqueue(Request::ptr_t request)
 {
 	if(request->isDead())
 	{
-		LL_DEBUGS("LLMediaDataClient") << "not queueing dead request " << *request << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClient") << "not queuing dead request " << *request << LL_ENDL;
 		return;
 	}
 	
+    PredicateMatchRequest upred(request);
+
 	// If there's already a matching request in the queue, remove it.
-	request_queue_t::iterator iter = find_matching_request(mQueue, request, LLMediaDataClient::Request::ANY);
+    request_queue_t::iterator iter = std::find_if(mQueue.begin(), mQueue.end(), upred);
 	if(iter != mQueue.end())
 	{
 		LL_DEBUGS("LLMediaDataClient") << "removing matching queued request " << (**iter) << LL_ENDL;
@@ -960,7 +997,7 @@ void LLObjectMediaNavigateClient::enqueue(Request *request)
 	}
 	else
 	{
-		request_set_t::iterator set_iter = find_matching_request(mUnQueuedRequests, request, LLMediaDataClient::Request::ANY);
+        request_set_t::iterator set_iter = std::find_if(mUnQueuedRequests.begin(), mUnQueuedRequests.end(), upred);
 		if(set_iter != mUnQueuedRequests.end())
 		{
 			LL_DEBUGS("LLMediaDataClient") << "removing matching unqueued request " << (**set_iter) << LL_ENDL;
@@ -979,7 +1016,7 @@ void LLObjectMediaNavigateClient::enqueue(Request *request)
 	else
 #endif
 	{
-		LL_DEBUGS("LLMediaDataClient") << "queueing new request " << (*request) << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClient") << "queuing new request " << (*request) << LL_ENDL;
 		mQueue.push_back(request);
 		
 		// Start the timer if not already running
@@ -993,7 +1030,7 @@ void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 t
 //	LL_INFOS("LLMediaDataClient") << "navigate() initiated: " << ll_print_sd(sd_payload) << LL_ENDL;
 	
 	// Create a get request and put it in the queue.
-	enqueue(new RequestNavigate(object, this, texture_index, url));
+	enqueue(Request::ptr_t(new RequestNavigate(object, this, texture_index, url)));
 }
 
 LLObjectMediaNavigateClient::RequestNavigate::RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url):
@@ -1012,75 +1049,67 @@ LLSD LLObjectMediaNavigateClient::RequestNavigate::getPayload() const
 	return result;
 }
 
-LLMediaDataClient::Responder *LLObjectMediaNavigateClient::RequestNavigate::createResponder()
+LLHttpSDHandler *LLObjectMediaNavigateClient::RequestNavigate::createHandler()
 {
-	return new LLObjectMediaNavigateClient::Responder(this);
+	return new LLObjectMediaNavigateClient::Handler(shared_from_this());
 }
 
-/*virtual*/
-void LLObjectMediaNavigateClient::Responder::httpFailure()
+void LLObjectMediaNavigateClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
 {
-	getRequest()->stopTracking();
+    LLMediaDataClient::Handler::onSuccess(response, content);
 
-	if(getRequest()->isDead())
-	{
-		LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL;
-		return;
-	}
+    if (getRequest()->isDead())
+    {   // already warned.
+        return;
+    }
+
+    LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned" << LL_ENDL;
+
+    if (content.has("error"))
+    {
+        const LLSD &error = content["error"];
+        int error_code = error["code"];
+
+        if (ERROR_PERMISSION_DENIED_CODE == error_code)
+        {
+            mediaNavigateBounceBack();
+        }
+        else
+        {
+            LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" <<
+                error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+        }
+
+        // XXX Warn user?
+    }
+    else
+    {
+        // No action required.
+        LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << LL_ENDL;
+    }
 
-	// Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base
-	// class
-	if (getStatus() == HTTP_SERVICE_UNAVAILABLE)
-	{
-		LLMediaDataClient::Responder::httpFailure();
-	}
-	else
-	{
-		// bounce the face back
-		LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: " << dumpResponse() << LL_ENDL;
-		const LLSD &payload = getRequest()->getPayload();
-		// bounce the face back
-		getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
-	}
 }
 
-/*virtual*/
-void LLObjectMediaNavigateClient::Responder::httpSuccess()
+void LLObjectMediaNavigateClient::Handler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status)
 {
-	getRequest()->stopTracking();
+    LLMediaDataClient::Handler::onFailure(response, status);
 
-	if(getRequest()->isDead())
-	{
-		LL_WARNS("LLMediaDataClient") << "dead request " << *(getRequest()) << LL_ENDL;
-		return;
-	}
+    if (getRequest()->isDead())
+    {   // already warned.
+        return;
+    }
 
-	LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << dumpResponse() << LL_ENDL;
-	
-	const LLSD& content = getContent();
-	if (content.has("error"))
-	{
-		const LLSD &error = content["error"];
-		int error_code = error["code"];
-		
-		if (ERROR_PERMISSION_DENIED_CODE == error_code)
-		{
-			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
-			const LLSD &payload = getRequest()->getPayload();
-			// bounce the face back
-			getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
-		}
-		else
-		{
-			LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" << 
-				error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
-		}			 
+    if (status != LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE))
+    {
+        mediaNavigateBounceBack();
+    }
+}
 
-		// XXX Warn user?
-	}
-	else 
-	{
-		// No action required.
-		LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " " << dumpResponse() << LL_ENDL;
-	}
+void LLObjectMediaNavigateClient::Handler::mediaNavigateBounceBack()
+{
+    LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating or denied." << LL_ENDL;
+    const LLSD &payload = getRequest()->getPayload();
+    
+    // bounce the face back
+    getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
 }
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 80dd5198124c9f126d72d44412ed5dbcea67cb2b..9907897613b4826f9dc6354a1f10cc9117c972e7 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -27,12 +27,15 @@
 #ifndef LL_LLMEDIADATACLIENT_H
 #define LL_LLMEDIADATACLIENT_H
 
-#include "llhttpclient.h"
 #include <set>
 #include "llrefcount.h"
 #include "llpointer.h"
 #include "lleventtimer.h"
-
+#include "llhttpsdhandler.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+#include "httpheaders.h"
 
 // Link seam for LLVOVolume
 class LLMediaDataClientObject : public LLRefCount
@@ -74,6 +77,8 @@ class LLMediaDataClientObject : public LLRefCount
 // Abstracts the Cap URL, the request, and the responder
 class LLMediaDataClient : public LLRefCount
 {
+    friend class PredicateMatchRequest;
+
 protected:
     LOG_CLASS(LLMediaDataClient);
 public:
@@ -109,26 +114,30 @@ class LLMediaDataClient : public LLRefCount
 	// Destructor
 	virtual ~LLMediaDataClient(); // use unref
     
-	class Responder;
-	
 	// Request (pure virtual base class for requests in the queue)
-	class Request : public LLRefCount
-	{
-	public:
-		// Subclasses must implement this to build a payload for their request type.
-		virtual LLSD getPayload() const = 0;
-		// and must create the correct type of responder.
-		virtual Responder *createResponder() = 0;
+    class Request: 
+        public boost::enable_shared_from_this<Request>
+    {
+    public:
+        typedef boost::shared_ptr<Request> ptr_t;
 
-		virtual std::string getURL() { return ""; }
+        // Subclasses must implement this to build a payload for their request type.
+        virtual LLSD getPayload() const = 0;
+        // and must create the correct type of responder.
+        virtual LLHttpSDHandler *createHandler() = 0;
+
+        virtual std::string getURL() { return ""; }
 
         enum Type {
             GET,
             UPDATE,
             NAVIGATE,
-			ANY
+            ANY
         };
-        
+
+        virtual ~Request()
+        { }
+
 	protected:
 		// The only way to create one of these is through a subclass.
 		Request(Type in_type, LLMediaDataClientObject *obj, LLMediaDataClient *mdc, S32 face = -1);
@@ -166,7 +175,7 @@ class LLMediaDataClient : public LLRefCount
 		const LLUUID &getID() const { return mObjectID; }
 		S32 getFace() const { return mFace; }
 		
-		bool isMatch (const Request* other, Type match_type = ANY) const 
+		bool isMatch (const Request::ptr_t &other, Type match_type = ANY) const 
 		{ 
 			return ((match_type == ANY) || (mType == other->mType)) && 
 					(mFace == other->mFace) && 
@@ -188,61 +197,62 @@ class LLMediaDataClient : public LLRefCount
 		// Back pointer to the MDC...not a ref!
 		LLMediaDataClient *mMDC;
 	};
-	typedef LLPointer<Request> request_ptr_t;
+	//typedef LLPointer<Request> request_ptr_t;
 
-	// Responder
-	class Responder : public LLHTTPClient::Responder
-	{
-		LOG_CLASS(Responder);
-	public:
-		Responder(const request_ptr_t &request);
-		request_ptr_t &getRequest() { return mRequest; }
+    class Handler : public LLHttpSDHandler
+    {
+        LOG_CLASS(Handler);
+    public:
+        Handler(const Request::ptr_t &request);
+        Request::ptr_t getRequest() const { return mRequest; }
 
-	protected:
-		//If we get back an error (not found, etc...), handle it here
-		virtual void httpFailure();
-		//If we get back a normal response, handle it here.	 Default just logs it.
-		virtual void httpSuccess();
+    protected:
+        virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+        virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
+
+    private:
+        Request::ptr_t mRequest;
+    };
 
-	private:
-		request_ptr_t mRequest;
-	};
 
 	class RetryTimer : public LLEventTimer
 	{
 	public:
-		RetryTimer(F32 time, request_ptr_t);
+		RetryTimer(F32 time, Request::ptr_t);
 		virtual BOOL tick();
 	private:
 		// back-pointer
-		request_ptr_t mRequest;
+		Request::ptr_t mRequest;
 	};
 		
 	
 protected:
-	typedef std::list<request_ptr_t> request_queue_t;
-	typedef std::set<request_ptr_t> request_set_t;
+	typedef std::list<Request::ptr_t> request_queue_t;
+	typedef std::set<Request::ptr_t> request_set_t;
 
 	// Subclasses must override to return a cap name
 	virtual const char *getCapabilityName() const = 0;
 
 	// Puts the request into a queue, appropriately handling duplicates, etc.
-	virtual void enqueue(Request*) = 0;
+    virtual void enqueue(Request::ptr_t) = 0;
 	
 	virtual void serviceQueue();
+    virtual void serviceHttp();
 
 	virtual request_queue_t *getQueue() { return &mQueue; };
 
 	// Gets the next request, removing it from the queue
-	virtual request_ptr_t dequeue();
+	virtual Request::ptr_t dequeue();
 	
-	virtual bool canServiceRequest(request_ptr_t request) { return true; };
+	virtual bool canServiceRequest(Request::ptr_t request) { return true; };
 
 	// Returns a request to the head of the queue (should only be used for requests that came from dequeue
-	virtual void pushBack(request_ptr_t request);
+	virtual void pushBack(Request::ptr_t request);
 	
-	void trackRequest(request_ptr_t request);
-	void stopTrackingRequest(request_ptr_t request);
+	void trackRequest(Request::ptr_t request);
+	void stopTrackingRequest(Request::ptr_t request);
+
+    bool isDoneProcessing() const;
 	
 	request_queue_t mQueue;
 
@@ -260,6 +270,11 @@ class LLMediaDataClient : public LLRefCount
 	void startQueueTimer();
 	void stopQueueTimer();
 
+    LLCore::HttpRequest::ptr_t  mHttpRequest;
+    LLCore::HttpHeaders::ptr_t  mHttpHeaders;
+    LLCore::HttpOptions::ptr_t  mHttpOpts;
+    LLCore::HttpRequest::policy_t mHttpPolicy;
+
 private:
 	
 	static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
@@ -281,9 +296,9 @@ class LLMediaDataClient : public LLRefCount
 		
 	bool mQueueTimerIsRunning;
 
-	template <typename T> friend typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type);
-	template <typename T> friend typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type);
-	template <typename T> friend void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type);
+// 	template <typename T> friend typename T::iterator find_matching_request(T &c, const LLMediaDataClient::Request *request, LLMediaDataClient::Request::Type match_type);
+// 	template <typename T> friend typename T::iterator find_matching_request(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type);
+// 	template <typename T> friend void remove_matching_requests(T &c, const LLUUID &id, LLMediaDataClient::Request::Type match_type);
 };
 
 // MediaDataClient specific for the ObjectMedia cap
@@ -309,7 +324,7 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 	public:
 		RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
 		/*virtual*/ LLSD getPayload() const;
-		/*virtual*/ Responder *createResponder();
+        /*virtual*/ LLHttpSDHandler *createHandler();
 	};
 
 	class RequestUpdate: public Request
@@ -317,7 +332,7 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 	public:
 		RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
 		/*virtual*/ LLSD getPayload() const;
-		/*virtual*/ Responder *createResponder();
+        /*virtual*/ LLHttpSDHandler *createHandler();
 	};
 
 	// Returns true iff the queue is empty
@@ -331,7 +346,7 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 
 	virtual bool processQueueTimer();
 
-	virtual bool canServiceRequest(request_ptr_t request);
+	virtual bool canServiceRequest(Request::ptr_t request);
 
 protected:
 	// Subclasses must override to return a cap name
@@ -340,17 +355,20 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 	virtual request_queue_t *getQueue();
 
 	// Puts the request into the appropriate queue
-	virtual void enqueue(Request*);
+	virtual void enqueue(Request::ptr_t);
 		    
-    class Responder : public LLMediaDataClient::Responder
+    class Handler: public LLMediaDataClient::Handler
     {
-        LOG_CLASS(Responder);
+        LOG_CLASS(Handler);
     public:
-        Responder(const request_ptr_t &request)
-            : LLMediaDataClient::Responder(request) {}
+        Handler(const Request::ptr_t &request):
+            LLMediaDataClient::Handler(request)
+        {}
+
     protected:
-        virtual void httpSuccess();
+        virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
     };
+
 private:
 	// The Get/Update data client needs a second queue to avoid object updates starving load-ins.
 	void swapCurrentQueue();
@@ -359,7 +377,7 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 	bool mCurrentQueueIsTheSortedQueue;
 
 	// Comparator for sorting
-	static bool compareRequestScores(const request_ptr_t &o1, const request_ptr_t &o2);
+	static bool compareRequestScores(const Request::ptr_t &o1, const Request::ptr_t &o2);
 	void sortQueue();
 };
 
@@ -384,14 +402,14 @@ class LLObjectMediaNavigateClient : public LLMediaDataClient
     void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
 
 	// Puts the request into the appropriate queue
-	virtual void enqueue(Request*);
+    virtual void enqueue(Request::ptr_t);
 
 	class RequestNavigate: public Request
 	{
 	public:
 		RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url);
 		/*virtual*/ LLSD getPayload() const;
-		/*virtual*/ Responder *createResponder();
+        /*virtual*/ LLHttpSDHandler *createHandler();
 		/*virtual*/ std::string getURL() { return mURL; }
 	private:
 		std::string mURL;
@@ -401,15 +419,18 @@ class LLObjectMediaNavigateClient : public LLMediaDataClient
 	// Subclasses must override to return a cap name
 	virtual const char *getCapabilityName() const;
 
-    class Responder : public LLMediaDataClient::Responder
+    class Handler : public LLMediaDataClient::Handler
     {
-        LOG_CLASS(Responder);
+        LOG_CLASS(Handler);
     public:
-        Responder(const request_ptr_t &request)
-            : LLMediaDataClient::Responder(request) {}
+        Handler(const Request::ptr_t &request):
+            LLMediaDataClient::Handler(request)
+        {}
+
     protected:
-        virtual void httpFailure();
-        virtual void httpSuccess();
+        virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content);
+        virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status);
+
     private:
         void mediaNavigateBounceBack();
     };
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 9a0bd9d1bc53977a7905bb65481894d805d68c56..457053f7131c71c244602a31dfca67f2fb8f3bed 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -36,7 +36,6 @@
 #include "llappviewer.h"
 #include "llbufferstream.h"
 #include "llcallbacklist.h"
-#include "llcurl.h"
 #include "lldatapacker.h"
 #include "lldeadmantimer.h"
 #include "llfloatermodelpreview.h"
@@ -73,6 +72,10 @@
 #include "llfasttimer.h"
 #include "llcorehttputil.h"
 #include "lltrans.h"
+#include "llstatusbar.h"
+#include "llinventorypanel.h"
+#include "lluploaddialog.h"
+#include "llfloaterreg.h"
 
 #include "boost/lexical_cast.hpp"
 
@@ -413,6 +416,17 @@ static unsigned int metrics_teleport_start_count = 0;
 boost::signals2::connection metrics_teleport_started_signal;
 static void teleport_started();
 
+void on_new_single_inventory_upload_complete(
+    LLAssetType::EType asset_type,
+    LLInventoryType::EType inventory_type,
+    const std::string inventory_type_string,
+    const LLUUID& item_folder_id,
+    const std::string& item_name,
+    const std::string& item_description,
+    const LLSD& server_response,
+    S32 upload_price);
+
+
 //get the number of bytes resident in memory for given volume
 U32 get_volume_memory_size(const LLVolume* volume)
 {
@@ -493,6 +507,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,
 	}
 }
 
+LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material)
+{
+	LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData);
+	return ppTex ? (*ppTex).get() : NULL;
+}
+
 volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
 volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;
 U32	LLMeshRepoThread::sMaxConcurrentRequests = 1;
@@ -587,16 +607,16 @@ class LLMeshLODHandler : public LLMeshHandlerBase
 	LLMeshLODHandler(const LLVolumeParams & mesh_params, S32 lod, U32 offset, U32 requested_bytes)
 		: LLMeshHandlerBase(offset, requested_bytes),
 		  mLOD(lod)
-		{
+	{
 			mMeshParams = mesh_params;
 			LLMeshRepoThread::incActiveLODRequests();
 		}
 	virtual ~LLMeshLODHandler();
-
+	
 protected:
 	LLMeshLODHandler(const LLMeshLODHandler &);					// Not defined
 	void operator=(const LLMeshLODHandler &);					// Not defined
-
+	
 public:
 	virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size);
 	virtual void processFailure(LLCore::HttpStatus status);
@@ -768,9 +788,9 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
 LLMeshRepoThread::LLMeshRepoThread()
 : LLThread("mesh repo"),
   mHttpRequest(NULL),
-  mHttpOptions(NULL),
-  mHttpLargeOptions(NULL),
-  mHttpHeaders(NULL),
+  mHttpOptions(),
+  mHttpLargeOptions(),
+  mHttpHeaders(),
   mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
   mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
   mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
@@ -783,20 +803,20 @@ LLMeshRepoThread::LLMeshRepoThread()
 	mHeaderMutex = new LLMutex(NULL);
 	mSignal = new LLCondition(NULL);
 	mHttpRequest = new LLCore::HttpRequest;
-	mHttpOptions = new LLCore::HttpOptions;
+	mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 	mHttpOptions->setTransferTimeout(SMALL_MESH_XFER_TIMEOUT);
 	mHttpOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
-	mHttpLargeOptions = new LLCore::HttpOptions;
+	mHttpLargeOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 	mHttpLargeOptions->setTransferTimeout(LARGE_MESH_XFER_TIMEOUT);
 	mHttpLargeOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
-	mHttpHeaders = new LLCore::HttpHeaders;
+	mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 	mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_VND_LL_MESH);
 	mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH2);
 	mHttpLegacyPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH1);
 	mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
 }
 
-			
+
 LLMeshRepoThread::~LLMeshRepoThread()
 {
 	LL_INFOS(LOG_MESH) << "Small GETs issued:  " << LLMeshRepository::sHTTPRequestCount
@@ -811,22 +831,9 @@ LLMeshRepoThread::~LLMeshRepoThread()
 		delete *iter;
 	}
 	mHttpRequestSet.clear();
-	if (mHttpHeaders)
-	{
-		mHttpHeaders->release();
-		mHttpHeaders = NULL;
-	}
-	if (mHttpOptions)
-	{
-		mHttpOptions->release();
-		mHttpOptions = NULL;
-	}
-	if (mHttpLargeOptions)
-	{
-		mHttpLargeOptions->release();
-		mHttpLargeOptions = NULL;
-	}
-	delete mHttpRequest;
+    mHttpHeaders.reset();
+
+    delete mHttpRequest;
 	mHttpRequest = NULL;
 	delete mMutex;
 	mMutex = NULL;
@@ -865,16 +872,16 @@ void LLMeshRepoThread::run()
 		{
 			break;
 		}
-
+		
 		if (! mHttpRequestSet.empty())
 		{
 			// Dispatch all HttpHandler notifications
 			mHttpRequest->update(0L);
 		}
 		sRequestWaterLevel = mHttpRequestSet.size();			// Stats data update
-
-		// NOTE: order of queue processing intentionally favors LOD requests over header requests
 			
+		// NOTE: order of queue processing intentionally favors LOD requests over header requests
+
 		while (!mLODReqQ.empty() && mHttpRequestSet.size() < sRequestHighWater)
 		{
 			if (! mMutex)
@@ -938,7 +945,7 @@ void LLMeshRepoThread::run()
 					mSkinRequests.erase(iter);
 					mMutex->unlock();
 
-					if (!fetchMeshSkinInfo(mesh_id))
+					if (! fetchMeshSkinInfo(mesh_id))
 					{
 						incomplete.insert(mesh_id);
 					}
@@ -967,7 +974,7 @@ void LLMeshRepoThread::run()
 					mDecompositionRequests.erase(iter);
 					mMutex->unlock();
 					
-					if (!fetchMeshDecomposition(mesh_id))
+					if (! fetchMeshDecomposition(mesh_id))
 					{
 						incomplete.insert(mesh_id);
 					}
@@ -993,7 +1000,7 @@ void LLMeshRepoThread::run()
 					mPhysicsShapeRequests.erase(iter);
 					mMutex->unlock();
 					
-					if (!fetchMeshPhysicsShape(mesh_id))
+					if (! fetchMeshPhysicsShape(mesh_id))
 					{
 						incomplete.insert(mesh_id);
 					}
@@ -1219,7 +1226,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 	}
 
 	++LLMeshRepository::sMeshRequestCount;
-	bool ret = true ;
+	bool ret = true;
 	U32 header_size = mMeshHeaderSize[mesh_id];
 	
 	if (header_size > 0)
@@ -1267,7 +1274,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
 			constructUrl(mesh_id, &http_url, &cap_version);
 
 			if (!http_url.empty())
-			{				
+			{
 				LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
 				LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
 				if (LLCORE_HTTP_HANDLE_INVALID == handle)
@@ -1313,7 +1320,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 
 	++LLMeshRepository::sMeshRequestCount;
 	U32 header_size = mMeshHeaderSize[mesh_id];
-	bool ret = true ;
+	bool ret = true;
 	
 	if (header_size > 0)
 	{
@@ -1359,9 +1366,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
 			int cap_version(2);
 			std::string http_url;
 			constructUrl(mesh_id, &http_url, &cap_version);
-
+			
 			if (!http_url.empty())
-			{				
+			{
 				LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
 				LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
 				if (LLCORE_HTTP_HANDLE_INVALID == handle)
@@ -1407,7 +1414,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 
 	++LLMeshRepository::sMeshRequestCount;
 	U32 header_size = mMeshHeaderSize[mesh_id];
-	bool ret = true ;
+	bool ret = true;
 
 	if (header_size > 0)
 	{
@@ -1452,9 +1459,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
 			int cap_version(2);
 			std::string http_url;
 			constructUrl(mesh_id, &http_url, &cap_version);
-
+			
 			if (!http_url.empty())
-			{				
+			{
 				LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
 				LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
 				if (LLCORE_HTTP_HANDLE_INVALID == handle)
@@ -1543,11 +1550,11 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
 	}
 
 	//either cache entry doesn't exist or is corrupt, request header from simulator	
-	bool retval = true ;
+	bool retval = true;
 	int cap_version(2);
 	std::string http_url;
 	constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
-
+	
 	if (!http_url.empty())
 	{
 		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits
@@ -1635,9 +1642,9 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 			int cap_version(2);
 			std::string http_url;
 			constructUrl(mesh_id, &http_url, &cap_version);
-
+			
 			if (!http_url.empty())
-			{				
+			{
 				LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
 				LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
 				if (LLCORE_HTTP_HANDLE_INVALID == handle)
@@ -1909,14 +1916,14 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
 
 	mOrigin += gAgent.getAtAxis() * scale.magVec();
 
-	mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
+	mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut");
 
 	mHttpRequest = new LLCore::HttpRequest;
-	mHttpOptions = new LLCore::HttpOptions;
+	mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 	mHttpOptions->setTransferTimeout(mMeshUploadTimeOut);
 	mHttpOptions->setUseRetryAfter(gSavedSettings.getBOOL("MeshUseHttpRetryAfter"));
 	mHttpOptions->setRetries(UPLOAD_RETRY_LIMIT);
-	mHttpHeaders = new LLCore::HttpHeaders;
+	mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 	mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS);
 	mHttpPriority = 0;
@@ -1924,16 +1931,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
 
 LLMeshUploadThread::~LLMeshUploadThread()
 {
-	if (mHttpHeaders)
-	{
-		mHttpHeaders->release();
-		mHttpHeaders = NULL;
-	}
-	if (mHttpOptions)
-	{
-		mHttpOptions->release();
-		mHttpOptions = NULL;
-	}
 	delete mHttpRequest;
 	mHttpRequest = NULL;
 }
@@ -1977,14 +1974,14 @@ void LLMeshUploadThread::preStart()
 
 void LLMeshUploadThread::discard()
 {
-	LLMutexLock lock(mMutex) ;
+	LLMutexLock lock(mMutex);
 	mDiscarded = true;
 }
 
 bool LLMeshUploadThread::isDiscarded() const
 {
-	LLMutexLock lock(mMutex) ;
-	return mDiscarded ;
+	LLMutexLock lock(mMutex);
+	return mDiscarded;
 }
 
 void LLMeshUploadThread::run()
@@ -2049,6 +2046,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
 	{
 		LLMeshUploadData data;
 		data.mBaseModel = iter->first;
+
+		if (data.mBaseModel->mSubmodelID)
+		{
+			// These are handled below to insure correct parenting order on creation
+			// due to map walking being based on model address (aka random)
+			continue;
+		}
+
 		LLModelInstance& first_instance = *(iter->second.begin());
 		for (S32 i = 0; i < 5; i++)
 		{
@@ -2086,7 +2091,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
 				data.mModel[LLModel::LOD_IMPOSTOR], 
 				decomp,
 				mUploadSkin,
-				mUploadJoints);
+				mUploadJoints,
+				FALSE,
+				FALSE,
+				data.mBaseModel->mSubmodelID);
 
 			data.mAssetData = ostr.str();
 			std::string str = ostr.str();
@@ -2120,17 +2128,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
 			instance_entry["scale"] = ll_sd_from_vector3(scale);
 		
 			instance_entry["material"] = LL_MCODE_WOOD;
-			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+			instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
 			instance_entry["mesh"] = mesh_index[data.mBaseModel];
 
 			instance_entry["face_list"] = LLSD::emptyArray();
 
-			S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
+			// We want to be able to allow more than 8 materials...
+			//
+			S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
+
 			for (S32 face_num = 0; face_num < end; face_num++)
 			{
 				LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
 				LLSD face_entry = LLSD::emptyMap();
-				LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
+
+				LLViewerFetchedTexture *texture = NULL;
+
+				if (material.mDiffuseMapFilename.size())
+				{
+					texture = FindViewerTexture(material);
+				}
 				
 				if ((texture != NULL) &&
 					(textures.find(texture) == textures.end()))
@@ -2145,9 +2162,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
 					{											
 						LLPointer<LLImageJ2C> upload_file =
 							LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+						if (!upload_file.isNull() && upload_file->getDataSize())
+						{
 						texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
 					}
 				}
+				}
+
+				if (texture != NULL &&
+					mUploadTextures &&
+					texture_index.find(texture) == texture_index.end())
+				{
+					texture_index[texture] = texture_num;
+					std::string str = texture_str.str();
+					res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
+					texture_num++;
+				}
+
+				// Subset of TextureEntry fields.
+				if (texture != NULL && mUploadTextures)
+				{
+					face_entry["image"] = texture_index[texture];
+					face_entry["scales"] = 1.0;
+					face_entry["scalet"] = 1.0;
+					face_entry["offsets"] = 0.0;
+					face_entry["offsett"] = 0.0;
+					face_entry["imagerot"] = 0.0;
+				}
+				face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+				face_entry["fullbright"] = material.mFullbright;
+				instance_entry["face_list"][face_num] = face_entry;
+		    }
+
+			res["instance_list"][instance_num] = instance_entry;
+			instance_num++;
+		}
+	}
+
+	for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+	{
+		LLMeshUploadData data;
+		data.mBaseModel = iter->first;
+
+		if (!data.mBaseModel->mSubmodelID)
+		{
+			// These were handled above already...
+			//
+			continue;
+		}
+
+		LLModelInstance& first_instance = *(iter->second.begin());
+		for (S32 i = 0; i < 5; i++)
+		{
+			data.mModel[i] = first_instance.mLOD[i];
+		}
+
+		if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+		{
+			// Have not seen this model before - create a new mesh_list entry for it.
+			if (model_name.empty())
+			{
+				model_name = data.mBaseModel->getName();
+			}
+
+			if (model_metric.empty())
+			{
+				model_metric = data.mBaseModel->getMetric();
+			}
+
+			std::stringstream ostr;
+			
+			LLModel::Decomposition& decomp =
+				data.mModel[LLModel::LOD_PHYSICS].notNull() ? 
+				data.mModel[LLModel::LOD_PHYSICS]->mPhysics : 
+				data.mBaseModel->mPhysics;
+
+			decomp.mBaseHull = mHullMap[data.mBaseModel];
+
+			LLSD mesh_header = LLModel::writeModel(
+				ostr,  
+				data.mModel[LLModel::LOD_PHYSICS],
+				data.mModel[LLModel::LOD_HIGH],
+				data.mModel[LLModel::LOD_MEDIUM],
+				data.mModel[LLModel::LOD_LOW],
+				data.mModel[LLModel::LOD_IMPOSTOR], 
+				decomp,
+				mUploadSkin,
+				mUploadJoints,
+				FALSE,
+				FALSE,
+				data.mBaseModel->mSubmodelID);
+
+			data.mAssetData = ostr.str();
+			std::string str = ostr.str();
+
+			res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); 
+			mesh_index[data.mBaseModel] = mesh_num;
+			mesh_num++;
+		}
+
+		// For all instances that use this model
+		for (instance_list::iterator instance_iter = iter->second.begin();
+			 instance_iter != iter->second.end();
+			 ++instance_iter)
+		{
+
+			LLModelInstance& instance = *instance_iter;
+		
+			LLSD instance_entry;
+		
+			for (S32 i = 0; i < 5; i++)
+			{
+				data.mModel[i] = instance.mLOD[i];
+			}
+		
+			LLVector3 pos, scale;
+			LLQuaternion rot;
+			LLMatrix4 transformation = instance.mTransform;
+			decomposeMeshMatrix(transformation,pos,rot,scale);
+			instance_entry["position"] = ll_sd_from_vector3(pos);
+			instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+			instance_entry["scale"] = ll_sd_from_vector3(scale);
+		
+			instance_entry["material"] = LL_MCODE_WOOD;
+			instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
+			instance_entry["mesh"] = mesh_index[data.mBaseModel];
+
+			instance_entry["face_list"] = LLSD::emptyArray();
+
+			// We want to be able to allow more than 8 materials...
+			//
+			S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
+
+			for (S32 face_num = 0; face_num < end; face_num++)
+			{
+				LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
+				LLSD face_entry = LLSD::emptyMap();
+
+				LLViewerFetchedTexture *texture = NULL;
+
+				if (material.mDiffuseMapFilename.size())
+				{
+					texture = FindViewerTexture(material);
+				}
+
+				if ((texture != NULL) &&
+					(textures.find(texture) == textures.end()))
+				{
+					textures.insert(texture);
+				}
+
+				std::stringstream texture_str;
+				if (texture != NULL && include_textures && mUploadTextures)
+				{
+					if(texture->hasSavedRawImage())
+					{											
+						LLPointer<LLImageJ2C> upload_file =
+							LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+						if (!upload_file.isNull() && upload_file->getDataSize())
+						{
+						texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+					}
+				}
+				}
 
 				if (texture != NULL &&
 					mUploadTextures &&
@@ -2235,7 +2414,7 @@ void LLMeshUploadThread::generateHulls()
 		}
 	}
 		
-	if(has_valid_requests)
+	if (has_valid_requests)
 	{
 		// *NOTE:  Interesting livelock condition on shutdown.  If there
 		// is an upload request in generateHulls() when shutdown starts,
@@ -2340,7 +2519,7 @@ void LLMeshUploadThread::requestWholeModelFee()
 	else
 	{
 		U32 sleep_time(10);
-
+		
 		mHttpRequest->update(0);
 		while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
 		{
@@ -2435,7 +2614,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
 		// model fee case
 		LLWholeModelFeeObserver* observer(mFeeObserverHandle.get());
 		mWholeModelUploadURL.clear();
-
+		
 		if (! status)
 		{
 			LL_WARNS(LOG_MESH) << "Fee request failed.  Reason:  " << reason
@@ -2465,7 +2644,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
 				LLCoreHttpUtil::responseToLLSD(response, true, body);
 			}
 			dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num));
-
+		
 			if (body["state"].asString() == "upload")
 			{
 				mWholeModelUploadURL = body["uploader"].asString();
@@ -2536,7 +2715,7 @@ void LLMeshRepoThread::notifyLoadedMeshes()
 		LODRequest req = mUnavailableQ.front();
 		mUnavailableQ.pop();
 		mMutex->unlock();
-		
+
 		update_metrics = true;
 		gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
 	}
@@ -2672,7 +2851,7 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
 void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
 {
 	mProcessed = true;
-	
+
 	unsigned int retries(0U);
 	response->getRetries(NULL, &retries);
 	LLMeshRepository::sHTTPRetryCount += retries;
@@ -2728,7 +2907,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo
 				// 200 case, typically
 				offset = 0;
 			}
-
+		
 			// *DEBUG:  To test validation below
 			// offset += 1;
 
@@ -2844,7 +3023,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 				const std::string & lod_name = header_lod[i];
 				lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger());
 			}
-
+		
 			// just in case skin info or decomposition is at the end of the file (which it shouldn't be)
 			lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
 			lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
@@ -2852,7 +3031,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 			S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
 			S32 bytes = lod_bytes + header_bytes; 
 
-
+		
 			// It's possible for the remote asset to have more data than is needed for the local cache
 			// only allocate as much space in the VFS as is needed for the local cache
 			data_size = llmin(data_size, bytes);
@@ -2864,11 +3043,11 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 				++LLMeshRepository::sCacheWrites;
 
 				file.write(data, data_size);
-
+			
 				// zero out the rest of the file 
 				U8 block[MESH_HEADER_SIZE];
 				memset(block, 0, sizeof(block));
-	
+
 				while (bytes-file.tell() > sizeof(block))
 				{
 					file.write(block, sizeof(block));
@@ -2894,8 +3073,8 @@ LLMeshLODHandler::~LLMeshLODHandler()
 			gMeshRepo.mThread->lockAndLoadMeshLOD(mMeshParams, mLOD);
 		}
 		LLMeshRepoThread::decActiveLODRequests();
-		}
 	}
+}
 
 void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)
 {
@@ -2913,7 +3092,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
 {
 	if ((! MESH_LOD_PROCESS_FAILED) && gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size))
 	{
-		//good fetch from sim, write to VFS for caching
+		// good fetch from sim, write to VFS for caching
 		LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE);
 
 		S32 offset = mOffset;
@@ -2958,7 +3137,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
 {
 	if ((! MESH_SKIN_INFO_PROCESS_FAILED) && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size))
 	{
-		//good fetch from sim, write to VFS for caching
+		// good fetch from sim, write to VFS for caching
 		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
 
 		S32 offset = mOffset;
@@ -3282,7 +3461,7 @@ void LLMeshRepository::notifyLoadedMeshes()
 													 REQUEST2_LOW_WATER_MIN,
 													 REQUEST2_LOW_WATER_MAX);
 	}
-
+	
 	//clean up completed upload threads
 	for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
 	{
@@ -3359,7 +3538,7 @@ void LLMeshRepository::notifyLoadedMeshes()
 
 	//call completed callbacks on finished decompositions
 	mDecompThread->notifyCompleted();
-	
+
 	// For major operations, attempt to get the required locks
 	// without blocking and punt if they're not available.  The
 	// longest run of holdoffs is kept in sMaxLockHoldoffs just
@@ -3378,12 +3557,12 @@ void LLMeshRepository::notifyLoadedMeshes()
 			return;
 		}
 		hold_offs = 0;
-
+		
 		if (gAgent.getRegion())
 		{
 			// Update capability urls
 			static std::string region_name("never name a region this");
-
+			
 			if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
 			{
 				region_name = gAgent.getRegion()->getName();
@@ -3399,7 +3578,7 @@ void LLMeshRepository::notifyLoadedMeshes()
 									<< LL_ENDL;
 			}
 		}
-
+		
 		//popup queued error messages from background threads
 		while (!mUploadErrorQ.empty())
 		{
@@ -3754,7 +3933,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
 
 
 void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
-									bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
+								   bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
 								   LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
 {
 	LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url, 
@@ -3825,37 +4004,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
 	result_rot = quat_rotation; 
 }
 
-bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
-{
-	if (mDiffuseMap != rhs.mDiffuseMap)
-	{
-		return mDiffuseMap < rhs.mDiffuseMap;
-	}
-
-	if (mDiffuseMapFilename != rhs.mDiffuseMapFilename)
-	{
-		return mDiffuseMapFilename < rhs.mDiffuseMapFilename;
-	}
-
-	if (mDiffuseMapLabel != rhs.mDiffuseMapLabel)
-	{
-		return mDiffuseMapLabel < rhs.mDiffuseMapLabel;
-	}
-
-	if (mDiffuseColor != rhs.mDiffuseColor)
-	{
-		return mDiffuseColor < rhs.mDiffuseColor;
-	}
-
-	if (mBinding != rhs.mBinding)
-	{
-		return mBinding < rhs.mBinding;
-	}
-
-	return mFullbright < rhs.mFullbright;
-}
-
-
 void LLMeshRepository::updateInventory(inventory_data data)
 {
 	LLMutexLock lock(mMeshMutex);
@@ -4253,7 +4401,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
 	setMeshData(mesh, true);
 
 	LLCDResult ret = decomp->buildSingleHull() ;
-	if(ret)
+	if (ret)
 	{
 		LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
 		make_box(mCurRequest);
@@ -4441,60 +4589,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
 	mStatusMessage = msg;
 }
 
-LLModelInstance::LLModelInstance(LLSD& data)
-{
-	mLocalMeshID = data["mesh_id"].asInteger();
-	mLabel = data["label"].asString();
-	mTransform.setValue(data["transform"]);
-
-	for (U32 i = 0; i < data["material"].size(); ++i)
-	{
-		LLImportMaterial mat(data["material"][i]);
-		mMaterial[mat.mBinding] = mat;
-	}
-}
-
-
-LLSD LLModelInstance::asLLSD()
-{	
-	LLSD ret;
-
-	ret["mesh_id"] = mModel->mLocalID;
-	ret["label"] = mLabel;
-	ret["transform"] = mTransform.getValue();
-	
-	U32 i = 0;
-	for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
-	{
-		ret["material"][i++] = iter->second.asLLSD();
-	}
-
-	return ret;
-}
-
-LLImportMaterial::LLImportMaterial(LLSD& data)
-{
-	mDiffuseMapFilename = data["diffuse"]["filename"].asString();
-	mDiffuseMapLabel = data["diffuse"]["label"].asString();
-	mDiffuseColor.setValue(data["diffuse"]["color"]);
-	mFullbright = data["fullbright"].asBoolean();
-	mBinding = data["binding"].asString();
-}
-
-
-LLSD LLImportMaterial::asLLSD()
-{
-	LLSD ret;
-
-	ret["diffuse"]["filename"] = mDiffuseMapFilename;
-	ret["diffuse"]["label"] = mDiffuseMapLabel;
-	ret["diffuse"]["color"] = mDiffuseColor.getValue();
-	ret["fullbright"] = mFullbright;
-	ret["binding"] = mBinding;
-
-	return ret;
-}
-
 void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
 {
 	decomp.mMesh.resize(decomp.mHull.size());
@@ -4620,3 +4714,122 @@ void teleport_started()
 	LLMeshRepository::metricsStart();
 }
 
+
+void on_new_single_inventory_upload_complete(
+    LLAssetType::EType asset_type,
+    LLInventoryType::EType inventory_type,
+    const std::string inventory_type_string,
+    const LLUUID& item_folder_id,
+    const std::string& item_name,
+    const std::string& item_description,
+    const LLSD& server_response,
+    S32 upload_price)
+{
+    bool success = false;
+
+    if (upload_price > 0)
+    {
+        // this upload costed us L$, update our balance
+        // and display something saying that it cost L$
+        LLStatusBar::sendMoneyBalanceRequest();
+
+        LLSD args;
+        args["AMOUNT"] = llformat("%d", upload_price);
+        LLNotificationsUtil::add("UploadPayment", args);
+    }
+
+    if (item_folder_id.notNull())
+    {
+        U32 everyone_perms = PERM_NONE;
+        U32 group_perms = PERM_NONE;
+        U32 next_owner_perms = PERM_ALL;
+        if (server_response.has("new_next_owner_mask"))
+        {
+            // The server provided creation perms so use them.
+            // Do not assume we got the perms we asked for in
+            // since the server may not have granted them all.
+            everyone_perms = server_response["new_everyone_mask"].asInteger();
+            group_perms = server_response["new_group_mask"].asInteger();
+            next_owner_perms = server_response["new_next_owner_mask"].asInteger();
+        }
+        else
+        {
+            // The server doesn't provide creation perms
+            // so use old assumption-based perms.
+            if (inventory_type_string != "snapshot")
+            {
+                next_owner_perms = PERM_MOVE | PERM_TRANSFER;
+            }
+        }
+
+        LLPermissions new_perms;
+        new_perms.init(
+            gAgent.getID(),
+            gAgent.getID(),
+            LLUUID::null,
+            LLUUID::null);
+
+        new_perms.initMasks(
+            PERM_ALL,
+            PERM_ALL,
+            everyone_perms,
+            group_perms,
+            next_owner_perms);
+
+        U32 inventory_item_flags = 0;
+        if (server_response.has("inventory_flags"))
+        {
+            inventory_item_flags = (U32)server_response["inventory_flags"].asInteger();
+            if (inventory_item_flags != 0)
+            {
+                LL_INFOS() << "inventory_item_flags " << inventory_item_flags << LL_ENDL;
+            }
+        }
+        S32 creation_date_now = time_corrected();
+        LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
+            server_response["new_inventory_item"].asUUID(),
+            item_folder_id,
+            new_perms,
+            server_response["new_asset"].asUUID(),
+            asset_type,
+            inventory_type,
+            item_name,
+            item_description,
+            LLSaleInfo::DEFAULT,
+            inventory_item_flags,
+            creation_date_now);
+
+        gInventory.updateItem(item);
+        gInventory.notifyObservers();
+        success = true;
+
+        // Show the preview panel for textures and sounds to let
+        // user know that the image (or snapshot) arrived intact.
+        LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel();
+        if (panel)
+        {
+            LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+
+            panel->setSelection(
+                server_response["new_inventory_item"].asUUID(),
+                TAKE_FOCUS_NO);
+
+            // restore keyboard focus
+            gFocusMgr.setKeyboardFocus(focus);
+        }
+    }
+    else
+    {
+        LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+    }
+
+    // remove the "Uploading..." message
+    LLUploadDialog::modalUploadFinished();
+
+    // Let the Snapshot floater know we have finished uploading a snapshot to inventory.
+    LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+    if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot)
+    {
+        floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+    }
+}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 39280bea3a5bd4665461af7169c0e1af0e501fb7..b33497730eb33a264e165a8d26278b156b0a1214 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -38,6 +38,7 @@
 #include "httpoptions.h"
 #include "httpheaders.h"
 #include "httphandler.h"
+#include "llthread.h"
 
 #define LLCONVEXDECOMPINTER_STATIC 1
 
@@ -90,54 +91,6 @@ class LLTextureUploadData
 	}
 };
 
-class LLImportMaterial
-{
-public:
-	LLPointer<LLViewerFetchedTexture> mDiffuseMap;
-	std::string mDiffuseMapFilename;
-	std::string mDiffuseMapLabel;
-	std::string mBinding;
-	LLColor4 mDiffuseColor;
-	bool mFullbright;
-
-	bool operator<(const LLImportMaterial &params) const;
-
-	LLImportMaterial() 
-		: mFullbright(false) 
-	{ 
-		mDiffuseColor.set(1,1,1,1);
-	}
-
-	LLImportMaterial(LLSD& data);
-
-	LLSD asLLSD();
-};
-
-class LLModelInstance 
-{
-public:
-	LLPointer<LLModel> mModel;
-	LLPointer<LLModel> mLOD[5];
-	
-	std::string mLabel;
-
-	LLUUID mMeshID;
-	S32 mLocalMeshID;
-
-	LLMatrix4 mTransform;
-	std::map<std::string, LLImportMaterial> mMaterial;
-
-	LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
-		: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
-	{
-		mLocalMeshID = -1;
-	}
-
-	LLModelInstance(LLSD& data);
-
-	LLSD asLLSD();
-};
-
 class LLPhysicsDecomp : public LLThread
 {
 public:
@@ -322,9 +275,9 @@ class LLMeshRepoThread : public LLThread
 	// llcorehttp library interface objects.
 	LLCore::HttpStatus					mHttpStatus;
 	LLCore::HttpRequest *				mHttpRequest;
-	LLCore::HttpOptions *				mHttpOptions;
-	LLCore::HttpOptions *				mHttpLargeOptions;
-	LLCore::HttpHeaders *				mHttpHeaders;
+	LLCore::HttpOptions::ptr_t			mHttpOptions;
+	LLCore::HttpOptions::ptr_t			mHttpLargeOptions;
+	LLCore::HttpHeaders::ptr_t			mHttpHeaders;
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;
 	LLCore::HttpRequest::policy_t		mHttpLegacyPolicyClass;
 	LLCore::HttpRequest::policy_t		mHttpLargePolicyClass;
@@ -483,6 +436,8 @@ class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler
 	// Inherited from LLCore::HttpHandler
 	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
 
+        LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
+
 private:
 	LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
 	LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
@@ -493,8 +448,8 @@ class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler
 	// llcorehttp library interface objects.
 	LLCore::HttpStatus					mHttpStatus;
 	LLCore::HttpRequest *				mHttpRequest;
-	LLCore::HttpOptions *				mHttpOptions;
-	LLCore::HttpHeaders *				mHttpHeaders;
+	LLCore::HttpOptions::ptr_t			mHttpOptions;
+	LLCore::HttpHeaders::ptr_t			mHttpHeaders;
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;
 	LLCore::HttpRequest::priority_t		mHttpPriority;
 };
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 3e7f05b5e16cc47ebaadbb884824edb01ab8d831..7a183cb298e9449ba39e0014fafcbe1cb3ecb2b0 100755
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -277,22 +277,6 @@ class LLBrowserNotification : public LLSystemNotificationHandler
 	virtual void initChannel() {};
 };
 	
-/**
- * Handler for outbox notifications
- */
-class LLOutboxNotification : public LLSystemNotificationHandler
-{
-public:
-	LLOutboxNotification();
-	virtual ~LLOutboxNotification() {};
-	virtual void onChange(LLNotificationPtr p) { }
-	virtual void onDelete(LLNotificationPtr p);
-	virtual bool processNotification(const LLNotificationPtr& p);
-
-protected:
-	virtual void initChannel() {};
-};
-	
 class LLHandlerUtil
 {
 public:
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 152581c5a0f5b362af1c5c173818f50a49dd78f0..a6f20a9f27f4ebd30be60f7d6512528f26a979d5 100755
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -61,7 +61,6 @@ void LLNotificationManager::init()
 	mChannels.push_back(new LLOfferHandler());
 	mChannels.push_back(new LLHintHandler());
 	mChannels.push_back(new LLBrowserNotification());
-	mChannels.push_back(new LLOutboxNotification());
 	mChannels.push_back(new LLIMHandler());
   
 	mChatHandler = boost::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler());
@@ -70,7 +69,7 @@ void LLNotificationManager::init()
 //--------------------------------------------------------------------------
 void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args)
 {
-	if(mChatHandler)
-		mChatHandler->processChat(msg, args);
-		}
+    if(mChatHandler)
+        mChatHandler->processChat(msg, args);
+}
 
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 878f1af9efae0da5e6113eff2da2795273a0f480..5d1ae4ff10c4b4e9928b58b4a5cc9a137c5eadf5 100755
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -34,14 +34,12 @@
 
 #include "lldispatcher.h"
 #include "llfloaterreg.h"
-#include "llhttpclient.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
 #include "llparcel.h"
 
 #include "llagent.h"
 #include "llclassifiedflags.h"
-#include "llclassifiedstatsresponder.h"
 #include "llcommandhandler.h" // for classified HTML detail page click tracking
 #include "lliconctrl.h"
 #include "lllineeditor.h"
@@ -57,6 +55,7 @@
 #include "llscrollcontainer.h"
 #include "llstatusbar.h"
 #include "llviewertexture.h"
+#include "llcorehttputil.h"
 
 const S32 MINIMUM_PRICE_FOR_LISTING = 50;	// L$
 
@@ -91,19 +90,6 @@ class LLDispatchClassifiedClickThrough : public LLDispatchHandler
 };
 static LLDispatchClassifiedClickThrough sClassifiedClickThrough;
 
-// Just to debug errors. Can be thrown away later.
-class LLClassifiedClickMessageResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLClassifiedClickMessageResponder);
-
-protected:
-	// If we get back an error (not found, etc...), handle it here
-	virtual void httpFailure()
-	{
-		LL_WARNS() << "Sending click message failed " << dumpResponse() << LL_ENDL;
-	}
-};
-
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
@@ -229,8 +215,10 @@ void LLPanelClassifiedInfo::onOpen(const LLSD& key)
 	{
 		LL_INFOS() << "Classified stat request via capability" << LL_ENDL;
 		LLSD body;
-		body["classified_id"] = getClassifiedId();
-		LLHTTPClient::post(url, body, new LLClassifiedStatsResponder(getClassifiedId()));
+        LLUUID classifiedId = getClassifiedId();
+		body["classified_id"] = classifiedId;
+        LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body,
+            boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1));
 	}
 
 	// Update classified click stats.
@@ -240,6 +228,23 @@ void LLPanelClassifiedInfo::onOpen(const LLSD& key)
 	setInfoLoaded(false);
 }
 
+/*static*/
+void LLPanelClassifiedInfo::handleSearchStatResponse(LLUUID classifiedId, LLSD result)
+{
+    S32 teleport = result["teleport_clicks"].asInteger();
+    S32 map = result["map_clicks"].asInteger();
+    S32 profile = result["profile_clicks"].asInteger();
+    S32 search_teleport = result["search_teleport_clicks"].asInteger();
+    S32 search_map = result["search_map_clicks"].asInteger();
+    S32 search_profile = result["search_profile_clicks"].asInteger();
+
+    LLPanelClassifiedInfo::setClickThrough(classifiedId,
+        teleport + search_teleport,
+        map + search_map,
+        profile + search_profile,
+        true);
+}
+
 void LLPanelClassifiedInfo::processProperties(void* data, EAvatarProcessorType type)
 {
 	if(APT_CLASSIFIED_INFO == type)
@@ -548,7 +553,8 @@ void LLPanelClassifiedInfo::sendClickMessage(
 	std::string url = gAgent.getRegion()->getCapability("SearchStatTracking");
 	LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL;
 	LL_INFOS() << "body: [" << body << "]" << LL_ENDL;
-	LLHTTPClient::post(url, body, new LLClassifiedClickMessageResponder());
+    LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
+        "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent.");
 }
 
 void LLPanelClassifiedInfo::sendClickMessage(const std::string& type)
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index cedd65c405a93dac67a68441dda8be66ceb67b96..b29278261543123e1464e013f75044b9ea974f34 100755
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -37,6 +37,8 @@
 #include "llrect.h"
 #include "lluuid.h"
 #include "v3dmath.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLScrollContainer;
 class LLTextureCtrl;
@@ -193,6 +195,9 @@ class LLPanelClassifiedInfo : public LLPanel, public LLAvatarPropertiesObserver
 	S32 mMapClicksNew;
 	S32 mProfileClicksNew;
 
+    static void handleSearchStatResponse(LLUUID classifiedId, LLSD result);
+
+
 	typedef std::list<LLPanelClassifiedInfo*> panel_list_t;
 	static panel_list_t sAllPanels;
 };
diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp
index fc4ee9862e93425d2f73586dadcab99197bacc0a..9d52a1906bd3cc8e9896838a614f4f0947b61352 100644
--- a/indra/newview/llpanelexperiencelisteditor.cpp
+++ b/indra/newview/llpanelexperiencelisteditor.cpp
@@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems()
 		columns[0]["value"] = getString("loading");
 		mItems->addElement(item);
 
-		LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, 
+        LLExperienceCache::instance().get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
 			getDerivedHandle<LLPanelExperienceListEditor>(), _1));
 	}
 
diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp
index df03ef752616d4869e9ef7f2ec555d00ac784528..d5979b6e96f75c93cea0e61b4bf88b92d2a8d5ac 100644
--- a/indra/newview/llpanelexperiencelog.cpp
+++ b/indra/newview/llpanelexperiencelog.cpp
@@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh()
 				}
 				const LLSD event = dayArray[i];
 				LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID();
-				const LLSD& experience = LLExperienceCache::get(id);
+                const LLSD& experience = LLExperienceCache::instance().get(id);
 				if(experience.isUndefined()){
 					waiting = true;
 					waiting_id = id;
@@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh()
 	{
 		mEventList->deleteAllItems();
 		mEventList->setCommentText(getString("loading"));
-		LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));
+        LLExperienceCache::instance().get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));
 	}
 	else
 	{
diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp
index 70d826a407f8d7e8e731df07a51fc45669211405..dcc5f4f234b0b8eb64b318c595eec76d51872342 100644
--- a/indra/newview/llpanelexperiencepicker.cpp
+++ b/indra/newview/llpanelexperiencepicker.cpp
@@ -58,41 +58,6 @@ const static std::string columnSpace = " ";
 
 static LLPanelInjector<LLPanelExperiencePicker> t_panel_status("llpanelexperiencepicker");
 
-class LLExperienceSearchResponder : public LLHTTPClient::Responder
-{
-public:
-	LLUUID mQueryID;
-	LLHandle<LLPanelExperiencePicker> mParent;
-
-	LLExperienceSearchResponder(const LLUUID& id, const LLHandle<LLPanelExperiencePicker>& parent) : mQueryID(id), mParent(parent) { }
-
-protected:
-	/*virtual*/ void httpSuccess()
-	{
-		if(mParent.isDead())
-			return;
-
-		LLPanelExperiencePicker* panel =mParent.get();
-		if (panel)
-		{
-			panel->processResponse(mQueryID, getContent());
-		}
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		if(mParent.isDead())
-			return;
-
-		LLPanelExperiencePicker* panel =mParent.get();
-		if (panel)
-		{
-			panel->processResponse(mQueryID, LLSD());
-		}
-		LL_WARNS() << "experience picker failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
-	}
-};
-
 LLPanelExperiencePicker::LLPanelExperiencePicker()
 	:LLPanel()
 {
@@ -163,17 +128,11 @@ void LLPanelExperiencePicker::find()
 {
 	std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
 	mQueryID.generate();
-	std::ostringstream url;
 
-	LLViewerRegion* region = gAgent.getRegion();
-	std::string cap = region->getCapability("FindExperienceByName");
-	if (!cap.empty())
-	{
-		url << cap << "?page=" << mCurrentPage << "&page_size=30&query=" << LLURI::escape(text);
-		LLHTTPClient::get(url.str(), new LLExperienceSearchResponder(mQueryID, getDerivedHandle<LLPanelExperiencePicker>()));
+    LLExperienceCache::instance().findExperienceByName(text, mCurrentPage,
+        boost::bind(&LLPanelExperiencePicker::findResults, getDerivedHandle<LLPanelExperiencePicker>(), mQueryID, _1));
 
-	}
-	getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
+    getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
 	getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
 	
 	getChildView(BTN_OK)->setEnabled(FALSE);
@@ -183,6 +142,19 @@ void LLPanelExperiencePicker::find()
 	getChildView(BTN_LEFT)->setEnabled(FALSE);
 }
 
+/*static*/
+void LLPanelExperiencePicker::findResults(LLHandle<LLPanelExperiencePicker> hparent, LLUUID queryId, LLSD foundResult)
+{
+    if (hparent.isDead())
+        return;
+
+    LLPanelExperiencePicker* panel = hparent.get();
+    if (panel)
+    {
+        panel->processResponse(queryId, foundResult);
+    }
+}
+
 
 bool LLPanelExperiencePicker::isSelectButtonEnabled()
 {
@@ -233,13 +205,6 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS
 
 	mResponse = content;
 
-	const LLSD& experiences=mResponse["experience_keys"];
-	LLSD::array_const_iterator it = experiences.beginArray();
-	for ( ; it != experiences.endArray(); ++it)
-	{
-		LLExperienceCache::insert(*it);
-	}
-
 	getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url"));
 	getChildView(BTN_LEFT)->setEnabled(content.has("previous_page_url"));
 
diff --git a/indra/newview/llpanelexperiencepicker.h b/indra/newview/llpanelexperiencepicker.h
index e39ffed70b21c8802eaa7fce8c9c782409c5abc7..97aa04cf4c96e9925b0b6b892e32a78e56e0ff7a 100644
--- a/indra/newview/llpanelexperiencepicker.h
+++ b/indra/newview/llpanelexperiencepicker.h
@@ -74,8 +74,9 @@ class LLPanelExperiencePicker : public LLPanel
 	void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids );
 	void setAllowMultiple(bool allow_multiple);
 
-
 	void find();
+    static void findResults(LLHandle<LLPanelExperiencePicker> hparent, LLUUID queryId, LLSD foundResult);
+
 	bool isSelectButtonEnabled();
 	void processResponse( const LLUUID& query_id, const LLSD& content );
 
diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp
index 76b68122fbbf16616a4e70947982a0b3da0ca27d..a88a55ab221611569e4980c34a3231adae1b93d6 100644
--- a/indra/newview/llpanelgroupexperiences.cpp
+++ b/indra/newview/llpanelgroupexperiences.cpp
@@ -31,45 +31,16 @@
 #include "lluictrlfactory.h"
 #include "roles_constants.h"
 
-#include "llhttpclient.h"
 #include "llagent.h"
 #include "llviewerregion.h"
 #include "llflatlistview.h"
 #include "llpanelexperiences.h"
 #include "llsd.h"
-
+#include "llexperiencecache.h"
 
 static LLPanelInjector<LLPanelGroupExperiences> t_panel_group_experiences("panel_group_experiences");
 
 
-class LLGroupExperienceResponder : public LLHTTPClient::Responder
-{
-public:
-	LLHandle<LLPanelGroupExperiences> mHandle;
-
-	LLGroupExperienceResponder(LLHandle<LLPanelGroupExperiences> handle) : mHandle(handle) { }
-
-protected:
-	/*virtual*/ void httpSuccess()
-	{
-		if (mHandle.isDead())
-		{
-			return;
-		}
-
-		LLPanelGroupExperiences* panel = mHandle.get();
-		if (panel)
-		{
-			panel->setExperienceList(getContent().get("experience_ids"));
-		}
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
-	}
-};
-
 LLPanelGroupExperiences::LLPanelGroupExperiences()
 :	LLPanelGroupTab(), mExperiencesList(NULL)
 {
@@ -101,14 +72,8 @@ void LLPanelGroupExperiences::activate()
 		return;
 	}
 
-	// search for experiences owned by the current group
-	std::string url = gAgent.getRegion()->getCapability("GroupExperiences"); 
-	if (!url.empty())
-	{
-		url += "?" + getGroupID().asString();
-		
-		LLHTTPClient::get(url, new LLGroupExperienceResponder(getDerivedHandle<LLPanelGroupExperiences>()));
-	}
+    LLExperienceCache::instance().getGroupExperiences(getGroupID(),
+        boost::bind(&LLPanelGroupExperiences::groupExperiencesResults, getDerivedHandle<LLPanelGroupExperiences>(), _1));
 }
 
 void LLPanelGroupExperiences::setGroupID(const LLUUID& id)
@@ -141,3 +106,19 @@ void LLPanelGroupExperiences::setExperienceList(const LLSD& experiences)
         mExperiencesList->addItem(item, public_key);
     }
 }
+
+/*static*/
+void LLPanelGroupExperiences::groupExperiencesResults(LLHandle<LLPanelGroupExperiences> handle, const LLSD &experiences)
+{
+    if (handle.isDead())
+    {
+        return;
+    }
+
+    LLPanelGroupExperiences* panel = handle.get();
+    if (panel)
+    {
+        panel->setExperienceList(experiences);
+    }
+
+}
diff --git a/indra/newview/llpanelgroupexperiences.h b/indra/newview/llpanelgroupexperiences.h
index ae1ecc1ac505caf20dd48c5143769aced00d04e7..7c79f7733250357bbd26faaeb8173e1663d1c0da 100644
--- a/indra/newview/llpanelgroupexperiences.h
+++ b/indra/newview/llpanelgroupexperiences.h
@@ -48,6 +48,9 @@ class LLPanelGroupExperiences : public LLPanelGroupTab
 
 protected:
 	LLFlatListView* mExperiencesList;
+
+private:
+    static void groupExperiencesResults(LLHandle<LLPanelGroupExperiences>, const LLSD &);
 };
 
 #endif
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 1d73d4bd6ed219a6223bd1fccdc858aa8ed69b0d..cd1dc0f0701de1e5173fe84d353a9449060df4c8 100755
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -1352,17 +1352,8 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark)
 	std::string url = region->getCapability("RemoteParcelRequest");
 	if (!url.empty())
 	{
-		body["location"] = ll_sd_from_vector3(region_pos);
-		if (!region_id.isNull())
-		{
-			body["region_id"] = region_id;
-		}
-		if (!pos_global.isExactlyZero())
-		{
-			U64 region_handle = to_region_handle(pos_global);
-			body["region_handle"] = ll_sd_from_U64(region_handle);
-		}
-		LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+        LLRemoteParcelInfoProcessor::getInstance()->requestRegionParcelInfo(url,
+            region_id, region_pos, pos_global, getObserverHandle());
 	}
 	else
 	{
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 953f234a53145bd48e355888f1ecb0f6a34bf1ec..360b1446049e9ace545086fdd0f2b96ab1bc1c31 100755
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -40,7 +40,6 @@
 #include "llcheckboxctrl.h"
 #include "llcommandhandler.h"		// for secondlife:///app/login/
 #include "llcombobox.h"
-#include "llcurl.h"
 #include "llviewercontrol.h"
 #include "llfloaterpreference.h"
 #include "llfocusmgr.h"
@@ -59,7 +58,6 @@
 #include "llviewernetwork.h"
 #include "llviewerwindow.h"			// to link into child list
 #include "lluictrlfactory.h"
-#include "llhttpclient.h"
 #include "llweb.h"
 #include "llmediactrl.h"
 #include "llrootview.h"
@@ -436,17 +434,10 @@ void LLPanelLogin::show(const LLRect &rect,
 						void (*callback)(S32 option, void* user_data),
 						void* callback_data)
 {
-	// instance management
-	if (LLPanelLogin::sInstance)
-	{
-		LL_WARNS("AppInit") << "Duplicate instance of login view deleted" << LL_ENDL;
-		// Don't leave bad pointer in gFocusMgr
-		gFocusMgr.setDefaultKeyboardFocus(NULL);
-
-		delete LLPanelLogin::sInstance;
-	}
-
-	new LLPanelLogin(rect, callback, callback_data);
+    if (!LLPanelLogin::sInstance)
+    {
+        new LLPanelLogin(rect, callback, callback_data);
+    }
 
 	if( !gFocusMgr.getKeyboardFocus() )
 	{
diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp
index cedd3025fc479dddd9ca630e6eae49027166ae13..55e4ffff5e10c5753dab5cfc0ee60e3301c47400 100755
--- a/indra/newview/llpanelme.cpp
+++ b/indra/newview/llpanelme.cpp
@@ -37,7 +37,6 @@
 #include "llfloaterreg.h"
 #include "llhints.h"
 #include "llviewercontrol.h"
-#include "llviewerdisplayname.h"
 
 // Linden libraries
 #include "llavatarnamecache.h"		// IDEVO
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index e62b5a4f1d6b384d2a9c41fe095723e1ac592461..cec56a7ae78773bafeed57da62674f6a3045eb75 100755
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -45,6 +45,7 @@
 #include "llpanelpick.h"
 #include "lltexturectrl.h"
 #include "llviewerregion.h"
+#include "llhttpconstants.h"
 
 LLPanelPlaceInfo::LLPanelPlaceInfo()
 :	LLPanel(),
@@ -150,17 +151,8 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
 	std::string url = region->getCapability("RemoteParcelRequest");
 	if (!url.empty())
 	{
-		body["location"] = ll_sd_from_vector3(mPosRegion);
-		if (!region_id.isNull())
-		{
-			body["region_id"] = region_id;
-		}
-		if (!pos_global.isExactlyZero())
-		{
-			U64 region_handle = to_region_handle(pos_global);
-			body["region_handle"] = ll_sd_from_U64(region_handle);
-		}
-		LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+        LLRemoteParcelInfoProcessor::getInstance()->requestRegionParcelInfo(url,
+            region_id, mPosRegion, pos_global, getObserverHandle());
 	}
 	else
 	{
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index 8e37b1418c14ffbfe44f76de9257a2cfc0f4154f..e4f39aac0450cdb5244776964b4dc237432ebda8 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -40,6 +40,7 @@
 #include "llpostcard.h"
 #include "llviewercontrol.h" // gSavedSettings
 #include "llviewerwindow.h"
+#include "llviewerregion.h"
 
 #include <boost/regex.hpp>
 
@@ -67,7 +68,8 @@ class LLPanelSnapshotPostcard
 	/*virtual*/ void updateControls(const LLSD& info);
 
 	bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
-	void sendPostcard();
+    static void sendPostcardFinished(LLSD result);
+    void sendPostcard();
 
 	void onMsgFormFocusRecieved();
 	void onFormatComboCommit(LLUICtrl* ctrl);
@@ -166,24 +168,44 @@ bool LLPanelSnapshotPostcard::missingSubjMsgAlertCallback(const LLSD& notificati
 }
 
 
-void LLPanelSnapshotPostcard::sendPostcard()
+void LLPanelSnapshotPostcard::sendPostcardFinished(LLSD result)
 {
-	std::string to(getChild<LLUICtrl>("to_form")->getValue().asString());
-	std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString());
+    LL_WARNS() << result << LL_ENDL;
 
-	LLSD postcard = LLSD::emptyMap();
-	postcard["pos-global"] = LLFloaterSnapshot::getPosTakenGlobal().getValue();
-	postcard["to"] = to;
-	postcard["from"] = mAgentEmail;
-	postcard["name"] = getChild<LLUICtrl>("name_form")->getValue().asString();
-	postcard["subject"] = subject;
-	postcard["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString();
-	LLPostCard::send(LLFloaterSnapshot::getImageData(), postcard);
+    std::string state = result["state"].asString();
 
-	// Give user feedback of the event.
-	gViewerWindow->playSnapshotAnimAndSound();
+    LLPostCard::reportPostResult((state == "complete"));
+}
 
-	LLFloaterSnapshot::postSave();
+
+void LLPanelSnapshotPostcard::sendPostcard()
+{
+    // upload the image
+    std::string url = gAgent.getRegion()->getCapability("SendPostcard");
+    if (!url.empty())
+    {
+        LLResourceUploadInfo::ptr_t uploadInfo(new LLPostcardUploadInfo(
+            mAgentEmail,
+            getChild<LLUICtrl>("name_form")->getValue().asString(),
+            getChild<LLUICtrl>("to_form")->getValue().asString(),
+            getChild<LLUICtrl>("subject_form")->getValue().asString(),
+            getChild<LLUICtrl>("msg_form")->getValue().asString(),
+            LLFloaterSnapshot::getPosTakenGlobal(),
+            LLFloaterSnapshot::getImageData(),
+            boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
+
+        LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+    }
+    else
+    {
+        LL_WARNS() << "Postcards unavailable in this region." << LL_ENDL;
+    }
+
+
+    // Give user feedback of the event.
+    gViewerWindow->playSnapshotAnimAndSound();
+
+    LLFloaterSnapshot::postSave();
 }
 
 void LLPanelSnapshotPostcard::onMsgFormFocusRecieved()
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index 4977a72dc692afcf655e1ebd74fa24af59ab34ba..711a869e823d478ac8a7946f7c94e2d0e98e3b67 100755
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -39,7 +39,6 @@
 #include <boost/signals2.hpp>
 
 #include "llagent.h"
-#include "llhttpclient.h"
 #include "llhttpnode.h"
 #include "llnotificationsutil.h"
 #include "llpathfindingcharacterlist.h"
@@ -55,6 +54,8 @@
 #include "lluuid.h"
 #include "llviewerregion.h"
 #include "llweb.h"
+#include "llcorehttputil.h"
+#include "llworld.h"
 
 #define CAP_SERVICE_RETRIEVE_NAVMESH        "RetrieveNavMeshSrc"
 
@@ -97,82 +98,6 @@ class LLAgentStateChangeNode : public LLHTTPNode
 
 LLHTTPRegistration<LLAgentStateChangeNode> gHTTPRegistrationAgentStateChangeNode(SIM_MESSAGE_AGENT_STATE_UPDATE);
 
-//---------------------------------------------------------------------------
-// NavMeshStatusResponder
-//---------------------------------------------------------------------------
-
-class NavMeshStatusResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(NavMeshStatusResponder);
-public:
-	NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly);
-	virtual ~NavMeshStatusResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	LLViewerRegion *mRegion;
-	LLUUID         mRegionUUID;
-	bool           mIsGetStatusOnly;
-};
-
-//---------------------------------------------------------------------------
-// NavMeshResponder
-//---------------------------------------------------------------------------
-
-class NavMeshResponder : public LLHTTPClient::Responder
-{
-    LOG_CLASS(NavMeshResponder);
-public:
-	NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
-	virtual ~NavMeshResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	U32                     mNavMeshVersion;
-	LLPathfindingNavMeshPtr mNavMeshPtr;
-};
-
-//---------------------------------------------------------------------------
-// AgentStateResponder
-//---------------------------------------------------------------------------
-
-class AgentStateResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(AgentStateResponder);
-public:
-	AgentStateResponder();
-	virtual ~AgentStateResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-};
-
-
-//---------------------------------------------------------------------------
-// NavMeshRebakeResponder
-//---------------------------------------------------------------------------
-class NavMeshRebakeResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(NavMeshRebakeResponder);
-public:
-	NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback);
-	virtual ~NavMeshRebakeResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback;
-};
-
 //---------------------------------------------------------------------------
 // LinksetsResponder
 //---------------------------------------------------------------------------
@@ -188,6 +113,8 @@ class LinksetsResponder
 	void handleTerrainLinksetsResult(const LLSD &pContent);
 	void handleTerrainLinksetsError();
 
+    typedef boost::shared_ptr<LinksetsResponder> ptr_t;
+
 protected:
 
 private:
@@ -213,64 +140,6 @@ class LinksetsResponder
 
 typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr;
 
-//---------------------------------------------------------------------------
-// ObjectLinksetsResponder
-//---------------------------------------------------------------------------
-
-class ObjectLinksetsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(ObjectLinksetsResponder);
-public:
-	ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
-	virtual ~ObjectLinksetsResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	LinksetsResponderPtr mLinksetsResponsderPtr;
-};
-
-//---------------------------------------------------------------------------
-// TerrainLinksetsResponder
-//---------------------------------------------------------------------------
-
-class TerrainLinksetsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(TerrainLinksetsResponder);
-public:
-	TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr);
-	virtual ~TerrainLinksetsResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	LinksetsResponderPtr mLinksetsResponsderPtr;
-};
-
-//---------------------------------------------------------------------------
-// CharactersResponder
-//---------------------------------------------------------------------------
-
-class CharactersResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(TerrainLinksetsResponder);
-public:
-	CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback);
-	virtual ~CharactersResponder();
-
-protected:
-	virtual void httpSuccess();
-	virtual void httpFailure();
-
-private:
-	LLPathfindingManager::request_id_t              mRequestId;
-	LLPathfindingManager::object_request_callback_t mCharactersCallback;
-};
-
 //---------------------------------------------------------------------------
 // LLPathfindingManager
 //---------------------------------------------------------------------------
@@ -350,11 +219,13 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, b
 	}
 	else
 	{
-		std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion);
-		llassert(!navMeshStatusURL.empty());
-		navMeshPtr->handleNavMeshCheckVersion();
-		LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(pRegion, pIsGetStatusOnly);
-		LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder);
+        std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion);
+        llassert(!navMeshStatusURL.empty());
+        navMeshPtr->handleNavMeshCheckVersion();
+
+        U64 regionHandle = pRegion->getHandle();
+        std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshStatusRequestCoro",
+            boost::bind(&LLPathfindingManager::navMeshStatusRequestCoro, this, navMeshStatusURL, regionHandle, pIsGetStatusOnly));
 	}
 }
 
@@ -385,15 +256,15 @@ void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_re
 			pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr);
 
 			bool doRequestTerrain = isAllowViewTerrainProperties();
-			LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain));
+			LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain));
 
-			LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
-			LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder);
+            std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro",
+                boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, LLSD()));
 
-			if (doRequestTerrain)
+            if (doRequestTerrain)
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
-				LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder);
+                std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro",
+                    boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, LLSD()));
 			}
 		}
 	}
@@ -432,18 +303,18 @@ void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLP
 		{
 			pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr);
 
-			LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, !objectPostData.isUndefined(), !terrainPostData.isUndefined()));
+			LinksetsResponder::ptr_t linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, !objectPostData.isUndefined(), !terrainPostData.isUndefined()));
 
 			if (!objectPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(linksetsResponderPtr);
-				LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder);
+                std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetObjectsCoro",
+                    boost::bind(&LLPathfindingManager::linksetObjectsCoro, this, objectLinksetsURL, linksetsResponderPtr, objectPostData));
 			}
 
 			if (!terrainPostData.isUndefined())
 			{
-				LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(linksetsResponderPtr);
-				LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder);
+                std::string coroname = LLCoros::instance().launch("LLPathfindingManager::linksetTerrainCoro",
+                    boost::bind(&LLPathfindingManager::linksetTerrainCoro, this, terrainLinksetsURL, linksetsResponderPtr, terrainPostData));
 			}
 		}
 	}
@@ -475,8 +346,8 @@ void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_
 		{
 			pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr);
 
-			LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(pRequestId, pCharactersCallback);
-			LLHTTPClient::get(charactersURL, charactersResponder);
+            std::string coroname = LLCoros::instance().launch("LLPathfindingManager::charactersCoro",
+                boost::bind(&LLPathfindingManager::charactersCoro, this, charactersURL, pRequestId, pCharactersCallback));
 		}
 	}
 }
@@ -508,8 +379,9 @@ void LLPathfindingManager::requestGetAgentState()
 		{
 			std::string agentStateURL = getAgentStateURLForRegion(currentRegion);
 			llassert(!agentStateURL.empty());
-			LLHTTPClient::ResponderPtr responder = new AgentStateResponder();
-			LLHTTPClient::get(agentStateURL, responder);
+
+            std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navAgentStateRequestCoro",
+                boost::bind(&LLPathfindingManager::navAgentStateRequestCoro, this, agentStateURL));
 		}
 	}
 }
@@ -530,35 +402,9 @@ void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebak
 	{
 		std::string navMeshStatusURL = getNavMeshStatusURLForCurrentRegion();
 		llassert(!navMeshStatusURL.empty());
-		LLSD postData;			
-		postData["command"] = "rebuild";
-		LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(pRebakeNavMeshCallback);
-		LLHTTPClient::post(navMeshStatusURL, postData, responder);
-	}
-}
-
-void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPtr navMeshPtr, LLViewerRegion *pRegion, const LLPathfindingNavMeshStatus &pNavMeshStatus)
-{
-	if ((pRegion == NULL) || !pRegion->isAlive())
-	{
-		navMeshPtr->handleNavMeshNotEnabled();
-	}
-	else
-	{
-		std::string navMeshURL = getRetrieveNavMeshURLForRegion(pRegion);
-
-		if (navMeshURL.empty())
-		{
-			navMeshPtr->handleNavMeshNotEnabled();
-		}
-		else
-		{
-			navMeshPtr->handleNavMeshStart(pNavMeshStatus);
-			LLHTTPClient::ResponderPtr responder = new NavMeshResponder(pNavMeshStatus.getVersion(), navMeshPtr);
 
-			LLSD postData;
-			LLHTTPClient::post(navMeshURL, postData, responder);
-		}
+        std::string coroname = LLCoros::instance().launch("LLPathfindingManager::navMeshRebakeCoro",
+                boost::bind(&LLPathfindingManager::navMeshRebakeCoro, this, navMeshStatusURL, pRebakeNavMeshCallback));
 	}
 }
 
@@ -602,29 +448,250 @@ void LLPathfindingManager::handleDeferredGetCharactersForRegion(const LLUUID &pR
 	}
 }
 
-void LLPathfindingManager::handleNavMeshStatusRequest(const LLPathfindingNavMeshStatus &pNavMeshStatus, LLViewerRegion *pRegion, bool pIsGetStatusOnly)
+void LLPathfindingManager::navMeshStatusRequestCoro(std::string url, U64 regionHandle, bool isGetStatusOnly)
 {
-	LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pNavMeshStatus.getRegionUUID());
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshStatusRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLViewerRegion *region = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+    if (!region)
+    {
+        LL_WARNS("PathfindingManager") << "Attempting to retrieve navmesh status for region that has gone away." << LL_ENDL;
+        return;
+    }
+    LLUUID regionUUID = region->getRegionID();
+
+    region = NULL;
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    region = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
 
-	if (!pNavMeshStatus.isValid())
-	{
-		navMeshPtr->handleNavMeshError();
-	}
-	else
-	{
-		if (navMeshPtr->hasNavMeshVersion(pNavMeshStatus))
-		{
-			navMeshPtr->handleRefresh(pNavMeshStatus);
-		}
-		else if (pIsGetStatusOnly)
-		{
-			navMeshPtr->handleNavMeshNewVersion(pNavMeshStatus);
-		}
-		else
-		{
-			sendRequestGetNavMeshForRegion(navMeshPtr, pRegion, pNavMeshStatus);
-		}
-	}
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    LLPathfindingNavMeshStatus navMeshStatus(regionUUID);
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() << 
+            ". Building using empty status." << LL_ENDL;
+    }
+    else
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        navMeshStatus = LLPathfindingNavMeshStatus(regionUUID, result);
+    }
+
+    LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(regionUUID);
+
+    if (!navMeshStatus.isValid())
+    {
+        navMeshPtr->handleNavMeshError();
+        return;
+    }
+    else if (navMeshPtr->hasNavMeshVersion(navMeshStatus))
+    {
+        navMeshPtr->handleRefresh(navMeshStatus);
+        return;
+    }
+    else if (isGetStatusOnly)
+    {
+        navMeshPtr->handleNavMeshNewVersion(navMeshStatus);
+        return;
+    }
+
+    if ((!region) || !region->isAlive())
+    {
+        LL_WARNS("PathfindingManager") << "About to update navmesh status for region that has gone away." << LL_ENDL;
+        navMeshPtr->handleNavMeshNotEnabled();
+        return;
+    }
+
+    std::string navMeshURL = getRetrieveNavMeshURLForRegion(region);
+
+    if (navMeshURL.empty())
+    {
+        navMeshPtr->handleNavMeshNotEnabled();
+        return;
+    }
+
+    navMeshPtr->handleNavMeshStart(navMeshStatus);
+
+    LLSD postData;
+    result = httpAdapter->postAndSuspend(httpRequest, navMeshURL, postData);
+
+    U32 navMeshVersion = navMeshStatus.getVersion();
+
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". reporting error." << LL_ENDL;
+        navMeshPtr->handleNavMeshError(navMeshVersion);
+    }
+    else
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        navMeshPtr->handleNavMeshResult(result, navMeshVersion);
+
+    }
+
+}
+
+void LLPathfindingManager::navAgentStateRequestCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavAgentStateRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    bool canRebake = false;
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". Building using empty status." << LL_ENDL;
+    }
+    else
+    {
+        llassert(result.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
+        llassert(result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
+        canRebake = result.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
+    }
+
+    handleAgentState(canRebake);
+}
+
+void LLPathfindingManager::navMeshRebakeCoro(std::string url, rebake_navmesh_callback_t rebakeNavMeshCallback)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavMeshRebake", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+
+    LLSD postData = LLSD::emptyMap();
+    postData["command"] = "rebuild";
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    bool success = true;
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". Rebake failed." << LL_ENDL;
+        success = false;
+    }
+       
+    rebakeNavMeshCallback(success);
+}
+
+// If called with putData undefined this coroutine will issue a get.  If there 
+// is data in putData it will be PUT to the URL.
+void LLPathfindingManager::linksetObjectsCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetObjects", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result;
+
+    if (putData.isUndefined())
+    {
+        result = httpAdapter->getAndSuspend(httpRequest, url);
+    }
+    else 
+    {
+        result = httpAdapter->putAndSuspend(httpRequest, url, putData);
+    }
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". linksetObjects failed." << LL_ENDL;
+        linksetsResponsderPtr->handleObjectLinksetsError();
+    }
+    else
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        linksetsResponsderPtr->handleObjectLinksetsResult(result);
+    }
+}
+
+// If called with putData undefined this coroutine will issue a GET.  If there 
+// is data in putData it will be PUT to the URL.
+void LLPathfindingManager::linksetTerrainCoro(std::string url, LinksetsResponder::ptr_t linksetsResponsderPtr, LLSD putData) const
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result;
+
+    if (putData.isUndefined())
+    {
+        result = httpAdapter->getAndSuspend(httpRequest, url);
+    }
+    else 
+    {
+        result = httpAdapter->putAndSuspend(httpRequest, url, putData);
+    }
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". linksetTerrain failed." << LL_ENDL;
+        linksetsResponsderPtr->handleTerrainLinksetsError();
+    }
+    else
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        linksetsResponsderPtr->handleTerrainLinksetsResult(result);
+    }
+
+}
+
+void LLPathfindingManager::charactersCoro(std::string url, request_id_t requestId, object_request_callback_t callback) const
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("PathfindingManager") << "HTTP status, " << status.toTerseString() <<
+            ". characters failed." << LL_ENDL;
+
+        LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList());
+        callback(requestId, LLPathfindingManager::kRequestError, characterListPtr);
+    }
+    else
+    {
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(result));
+        callback(requestId, LLPathfindingManager::kRequestCompleted, characterListPtr);
+    }
 }
 
 void LLPathfindingManager::handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus)
@@ -764,122 +831,9 @@ void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, c
 	LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion);
 }
 
-//---------------------------------------------------------------------------
-// NavMeshStatusResponder
-//---------------------------------------------------------------------------
-
-NavMeshStatusResponder::NavMeshStatusResponder(LLViewerRegion *pRegion, bool pIsGetStatusOnly)
-	: LLHTTPClient::Responder(),
-	mRegion(pRegion),
-	mRegionUUID(),
-	mIsGetStatusOnly(pIsGetStatusOnly)
-{
-	if (mRegion != NULL)
-	{
-		mRegionUUID = mRegion->getRegionID();
-	}
-}
-
-NavMeshStatusResponder::~NavMeshStatusResponder()
-{
-}
-
-void NavMeshStatusResponder::httpSuccess()
-{
-	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, getContent());
-	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
-}
-
-void NavMeshStatusResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID);
-	LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly);
-}
-
-//---------------------------------------------------------------------------
-// NavMeshResponder
-//---------------------------------------------------------------------------
-
-NavMeshResponder::NavMeshResponder(U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
-	: LLHTTPClient::Responder(),
-	mNavMeshVersion(pNavMeshVersion),
-	mNavMeshPtr(pNavMeshPtr)
-{
-}
-
-NavMeshResponder::~NavMeshResponder()
-{
-}
-
-void NavMeshResponder::httpSuccess()
-{
-	mNavMeshPtr->handleNavMeshResult(getContent(), mNavMeshVersion);
-}
-
-void NavMeshResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	mNavMeshPtr->handleNavMeshError(mNavMeshVersion);
-}
-
-//---------------------------------------------------------------------------
-// AgentStateResponder
-//---------------------------------------------------------------------------
-
-AgentStateResponder::AgentStateResponder()
-: LLHTTPClient::Responder()
-{
-}
-
-AgentStateResponder::~AgentStateResponder()
-{
-}
-
-void AgentStateResponder::httpSuccess()
-{
-	const LLSD& pContent = getContent();
-	llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD));
-	llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean());
-	BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean();
-	LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion);
-}
-
-void AgentStateResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	LLPathfindingManager::getInstance()->handleAgentState(FALSE);
-}
-
-
-//---------------------------------------------------------------------------
-// navmesh rebake responder
-//---------------------------------------------------------------------------
-NavMeshRebakeResponder::NavMeshRebakeResponder(LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback)
-	: LLHTTPClient::Responder(),
-	mRebakeNavMeshCallback(pRebakeNavMeshCallback)
-{
-}
-
-NavMeshRebakeResponder::~NavMeshRebakeResponder()
-{
-}
-
-void NavMeshRebakeResponder::httpSuccess()
-{
-	mRebakeNavMeshCallback(true);
-}
-
-void NavMeshRebakeResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	mRebakeNavMeshCallback(false);
-}
-
 //---------------------------------------------------------------------------
 // LinksetsResponder
 //---------------------------------------------------------------------------
-
 LinksetsResponder::LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested)
 	: mRequestId(pRequestId),
 	mLinksetsCallback(pLinksetsCallback),
@@ -957,82 +911,3 @@ void LinksetsResponder::sendCallback()
 
 	mLinksetsCallback(mRequestId, requestStatus, mObjectLinksetListPtr);
 }
-
-//---------------------------------------------------------------------------
-// ObjectLinksetsResponder
-//---------------------------------------------------------------------------
-
-ObjectLinksetsResponder::ObjectLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
-	: LLHTTPClient::Responder(),
-	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
-{
-}
-
-ObjectLinksetsResponder::~ObjectLinksetsResponder()
-{
-}
-
-void ObjectLinksetsResponder::httpSuccess()
-{
-	mLinksetsResponsderPtr->handleObjectLinksetsResult(getContent());
-}
-
-void ObjectLinksetsResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	mLinksetsResponsderPtr->handleObjectLinksetsError();
-}
-
-//---------------------------------------------------------------------------
-// TerrainLinksetsResponder
-//---------------------------------------------------------------------------
-
-TerrainLinksetsResponder::TerrainLinksetsResponder(LinksetsResponderPtr pLinksetsResponsderPtr)
-	: LLHTTPClient::Responder(),
-	mLinksetsResponsderPtr(pLinksetsResponsderPtr)
-{
-}
-
-TerrainLinksetsResponder::~TerrainLinksetsResponder()
-{
-}
-
-void TerrainLinksetsResponder::httpSuccess()
-{
-	mLinksetsResponsderPtr->handleTerrainLinksetsResult(getContent());
-}
-
-void TerrainLinksetsResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-	mLinksetsResponsderPtr->handleTerrainLinksetsError();
-}
-
-//---------------------------------------------------------------------------
-// CharactersResponder
-//---------------------------------------------------------------------------
-
-CharactersResponder::CharactersResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback)
-	: LLHTTPClient::Responder(),
-	mRequestId(pRequestId),
-	mCharactersCallback(pCharactersCallback)
-{
-}
-
-CharactersResponder::~CharactersResponder()
-{
-}
-
-void CharactersResponder::httpSuccess()
-{
-	LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(getContent()));
-	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr);
-}
-
-void CharactersResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-
-	LLPathfindingObjectListPtr characterListPtr =  LLPathfindingObjectListPtr(new LLPathfindingCharacterList());
-	mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr);
-}
diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h
index c61ff244fc1a4549db5c78535cad9633823d28a1..e8fad590ba7c9e8cb0a04fe7d87d82be37a3e970 100755
--- a/indra/newview/llpathfindingmanager.h
+++ b/indra/newview/llpathfindingmanager.h
@@ -37,11 +37,15 @@
 #include "llpathfindingobjectlist.h"
 #include "llpathfindingnavmesh.h"
 #include "llsingleton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLPathfindingNavMeshStatus;
 class LLUUID;
 class LLViewerRegion;
 
+class LinksetsResponder;
+
 class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 {
 	friend class LLNavMeshSimStateChangeNode;
@@ -92,16 +96,22 @@ class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 protected:
 
 private:
-	typedef std::map<LLUUID, LLPathfindingNavMeshPtr> NavMeshMap;
 
-	void sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPtr navMeshPtr, LLViewerRegion *pRegion, const LLPathfindingNavMeshStatus &pNavMeshStatus);
+	typedef std::map<LLUUID, LLPathfindingNavMeshPtr> NavMeshMap;
 
 	void handleDeferredGetAgentStateForRegion(const LLUUID &pRegionUUID);
 	void handleDeferredGetNavMeshForRegion(const LLUUID &pRegionUUID, bool pIsGetStatusOnly);
 	void handleDeferredGetLinksetsForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const;
 	void handleDeferredGetCharactersForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pCharactersCallback) const;
 
-	void handleNavMeshStatusRequest(const LLPathfindingNavMeshStatus &pNavMeshStatus, LLViewerRegion *pRegion, bool pIsGetStatusOnly);
+    void navMeshStatusRequestCoro(std::string url, U64 regionHandle, bool isGetStatusOnly);
+    void navAgentStateRequestCoro(std::string url);
+    void navMeshRebakeCoro(std::string url, rebake_navmesh_callback_t rebakeNavMeshCallback);
+    void linksetObjectsCoro(std::string url, boost::shared_ptr<LinksetsResponder> linksetsResponsderPtr, LLSD putData) const;
+    void linksetTerrainCoro(std::string url, boost::shared_ptr<LinksetsResponder> linksetsResponsderPtr, LLSD putData) const;
+    void charactersCoro(std::string url, request_id_t requestId, object_request_callback_t callback) const;
+
+	//void handleNavMeshStatusRequest(const LLPathfindingNavMeshStatus &pNavMeshStatus, LLViewerRegion *pRegion, bool pIsGetStatusOnly);
 	void handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus);
 
 	void handleAgentState(BOOL pCanRebakeRegion);
diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp
index 5987044bffe2191a7ebc72d3a53daf14c890cda4..2e639b56ebfcf49c5f39668f3c6053149425f00a 100755
--- a/indra/newview/llpostcard.cpp
+++ b/indra/newview/llpostcard.cpp
@@ -36,122 +36,42 @@
 
 #include "llagent.h"
 #include "llassetstorage.h"
-#include "llassetuploadresponders.h"
+#include "llviewerassetupload.h"
 
 ///////////////////////////////////////////////////////////////////////////////
-// misc
 
-static void postcard_upload_callback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status)
+LLPostcardUploadInfo::LLPostcardUploadInfo(std::string emailFrom, std::string nameFrom, std::string emailTo,
+        std::string subject, std::string message, LLVector3d globalPosition,
+        LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
+    LLBufferedAssetUploadInfo(LLUUID::null, image, finish),
+    mEmailFrom(emailFrom),
+    mNameFrom(nameFrom),
+    mEmailTo(emailTo),
+    mSubject(subject),
+    mMessage(message),
+    mGlobalPosition(globalPosition)
 {
-	LLSD* postcard_data = (LLSD*)user_data;
-
-	if (result)
-	{
-		// TODO: display the error messages in UI
-		LL_WARNS() << "Failed to send postcard: " << LLAssetStorage::getErrorString(result) << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-	else
-	{
-		// only create the postcard once the upload succeeds
-
-		// request the postcard
-		const LLSD& data = *postcard_data;
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessage("SendPostcard");
-		msg->nextBlock("AgentData");
-		msg->addUUID("AgentID",			gAgent.getID());
-		msg->addUUID("SessionID",		gAgent.getSessionID());
-		msg->addUUID("AssetID",			data["asset-id"].asUUID());
-		msg->addVector3d("PosGlobal",	LLVector3d(data["pos-global"]));
-		msg->addString("To",			data["to"]);
-		msg->addString("From",			data["from"]);
-		msg->addString("Name",			data["name"]);
-		msg->addString("Subject",		data["subject"]);
-		msg->addString("Msg",			data["msg"]);
-		msg->addBOOL("AllowPublish",	FALSE);
-		msg->addBOOL("MaturePublish",	FALSE);
-		gAgent.sendReliableMessage();
-
-		LLPostCard::reportPostResult(true);
-	}
-
-	delete postcard_data;
 }
 
-
-///////////////////////////////////////////////////////////////////////////////
-// LLPostcardSendResponder
-
-class LLPostcardSendResponder : public LLAssetUploadResponder
+LLSD LLPostcardUploadInfo::generatePostBody()
 {
-	LOG_CLASS(LLPostcardSendResponder);
-
-public:
-	LLPostcardSendResponder(const LLSD &post_data,
-							const LLUUID& vfile_id,
-							LLAssetType::EType asset_type):
-	    LLAssetUploadResponder(post_data, vfile_id, asset_type)
-	{
-	}
-
-	/*virtual*/ void httpFailure()
-	{
-		LL_WARNS() << "Sending postcard failed, status: " << getStatus() << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-
-	/*virtual*/ void uploadComplete(const LLSD& content)
-	{
-		LL_INFOS() << "Postcard sent" << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "content: " << content << LL_ENDL;
-		LLPostCard::reportPostResult(true);
-	}
+    LLSD postcard = LLSD::emptyMap();
+    postcard["pos-global"] = mGlobalPosition.getValue();
+    postcard["to"] = mEmailTo;
+    postcard["from"] = mEmailFrom;
+    postcard["name"] = mNameFrom;
+    postcard["subject"] = mSubject;
+    postcard["msg"] = mMessage;
+
+    return postcard;
+}
 
-	/*virtual*/ void uploadFailure(const LLSD& content)
-	{
-		LL_WARNS() << "Sending postcard failed: " << content << LL_ENDL;
-		LLPostCard::reportPostResult(false);
-	}
-};
 
 ///////////////////////////////////////////////////////////////////////////////
 // LLPostCard
 
 LLPostCard::result_callback_t LLPostCard::mResultCallback;
 
-// static
-void LLPostCard::send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data)
-{
-	LLTransactionID transaction_id;
-	LLAssetID asset_id;
-
-	transaction_id.generate();
-	asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID());
-	LLVFile::writeFile(image->getData(), image->getDataSize(), gVFS, asset_id, LLAssetType::AT_IMAGE_JPEG);
-
-	// upload the image
-	std::string url = gAgent.getRegion()->getCapability("SendPostcard");
-	if (!url.empty())
-	{
-		LL_INFOS() << "Sending postcard via capability" << LL_ENDL;
-		// the capability already encodes: agent ID, region ID
-		LL_DEBUGS("Snapshots") << "url: " << url << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "body: " << postcard_data << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "data size: " << image->getDataSize() << LL_ENDL;
-		LLHTTPClient::post(url, postcard_data,
-			new LLPostcardSendResponder(postcard_data, asset_id, LLAssetType::AT_IMAGE_JPEG));
-	}
-	else
-	{
-		LL_INFOS() << "Sending postcard" << LL_ENDL;
-		LLSD* data = new LLSD(postcard_data);
-		(*data)["asset-id"] = asset_id;
-		gAssetStorage->storeAssetData(transaction_id, LLAssetType::AT_IMAGE_JPEG,
-			&postcard_upload_callback, (void *)data, FALSE);
-	}
-}
-
 // static
 void LLPostCard::reportPostResult(bool ok)
 {
diff --git a/indra/newview/llpostcard.h b/indra/newview/llpostcard.h
index 0eb118b90625e757468f7162d79f4767dd9a7190..24157be636ddb3ed6d0ff5234a0a387cee15e1f8 100755
--- a/indra/newview/llpostcard.h
+++ b/indra/newview/llpostcard.h
@@ -29,7 +29,12 @@
 
 #include "llimage.h"
 #include "lluuid.h"
+#include "llviewerassetupload.h"
 
+/// *TODO$: this LLPostCard class is a hold over and should be removed.  Right now
+/// all it does is hold a pointer to a call back function which is invoked by 
+/// llpanelsnapshotpostcard's finish function. (and all that call back does is 
+/// set the status in the floater.
 class LLPostCard
 {
 	LOG_CLASS(LLPostCard);
@@ -37,7 +42,6 @@ class LLPostCard
 public:
 	typedef boost::function<void(bool ok)> result_callback_t;
 
-	static void send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data);
 	static void setPostResultCallback(result_callback_t cb) { mResultCallback = cb; }
 	static void reportPostResult(bool ok);
 
@@ -45,4 +49,24 @@ class LLPostCard
 	static result_callback_t mResultCallback;
 };
 
+
+class LLPostcardUploadInfo : public LLBufferedAssetUploadInfo
+{
+public:
+    LLPostcardUploadInfo(std::string emailFrom, std::string nameFrom, std::string emailTo,
+        std::string subject, std::string message, LLVector3d globalPosition,
+        LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
+
+    virtual LLSD generatePostBody();
+private:
+    std::string mEmailFrom;
+    std::string mNameFrom;
+    std::string mEmailTo;
+    std::string mSubject;
+    std::string mMessage;
+    LLVector3d mGlobalPosition;
+
+};
+
+
 #endif // LL_LLPOSTCARD_H
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index c378738b05bcedabf9742ea0ebda871b5930742e..ff9a70d05c9edd2efbe05d4c4614cbd757996400 100755
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -31,7 +31,6 @@
 #include "llanimstatelabels.h"
 #include "llanimationstates.h"
 #include "llappviewer.h"			// gVFS
-#include "llassetuploadresponders.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "lldatapacker.h"
@@ -52,6 +51,7 @@
 #include "llviewerobjectlist.h"
 #include "llviewerregion.h"
 #include "llviewerstats.h"
+#include "llviewerassetupload.h"
 
 std::string NONE_LABEL;
 std::string SHIFT_LABEL;
@@ -1015,6 +1015,27 @@ struct LLSaveInfo
 };
 
 
+void LLPreviewGesture::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId)
+{
+    // If this gesture is active, then we need to update the in-memory
+    // active map with the new pointer.				
+    if (LLGestureMgr::instance().isGestureActive(itemId))
+    {
+        //*TODO: This is crashing for some reason.  Fix it.
+        // Active gesture edited from menu.
+        LLGestureMgr::instance().replaceGesture(itemId, newAssetId);
+        gInventory.notifyObservers();
+    }
+
+    //gesture will have a new asset_id
+    LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance<LLPreviewGesture>("preview_gesture", LLSD(itemId));
+    if (previewp)
+    {
+        previewp->onUpdateSucceeded();
+    }
+}
+
+
 void LLPreviewGesture::saveIfNeeded()
 {
 	if (!gAssetStorage)
@@ -1028,116 +1049,127 @@ void LLPreviewGesture::saveIfNeeded()
 		return;
 	}
 
-	// Copy the UI into a gesture
-	LLMultiGesture* gesture = createGesture();
-
-	// Serialize the gesture
-	S32 max_size = gesture->getMaxSerialSize();
-	char* buffer = new char[max_size];
-
-	LLDataPackerAsciiBuffer dp(buffer, max_size);
-
-	BOOL ok = gesture->serialize(dp);
-
-	if (dp.getCurrentSize() > 1000)
-	{
-		LLNotificationsUtil::add("GestureSaveFailedTooManySteps");
-
-		delete gesture;
-		gesture = NULL;
-	}
-	else if (!ok)
-	{
-		LLNotificationsUtil::add("GestureSaveFailedTryAgain");
-		delete gesture;
-		gesture = NULL;
-	}
-	else
-	{
-		LLPreview::onCommit();
-
-		// Every save gets a new UUID.  Yup.
-		LLTransactionID tid;
-		LLAssetID asset_id;
-		tid.generate();
-		asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
-		LLVFile file(gVFS, asset_id, LLAssetType::AT_GESTURE, LLVFile::APPEND);
-
-		S32 size = dp.getCurrentSize();
-		file.setMaxSize(size);
-		file.write((U8*)buffer, size);
-
-		BOOL delayedUpload = FALSE;
-
-		// Upload that asset to the database
-		LLViewerInventoryItem* item = (LLViewerInventoryItem*) getItem();
-		if (item)
-		{
-			std::string agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory");
-			std::string task_url = gAgent.getRegion()->getCapability("UpdateGestureTaskInventory");
-			if (mObjectUUID.isNull() && !agent_url.empty())
-			{
-				//need to disable the preview floater so item
-				//isn't re-saved before new asset arrives
-				//fake out refresh.
-				item->setComplete(FALSE);
-				refresh();				
-				item->setComplete(TRUE);
-
-				// Saving into agent inventory
-				LLSD body;
-				body["item_id"] = mItemUUID;
-				LLHTTPClient::post(agent_url, body,
-					new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
-				delayedUpload = TRUE;
-			}
-			else if (!mObjectUUID.isNull() && !task_url.empty())
-			{
-				// Saving into task inventory
-				LLSD body;
-				body["task_id"] = mObjectUUID;
-				body["item_id"] = mItemUUID;
-				LLHTTPClient::post(task_url, body,
-					new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE));
-			}
-			else if (gAssetStorage)
-			{
-				LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
-				LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
-				gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
-			}
-		}
-
-		// If this gesture is active, then we need to update the in-memory
-		// active map with the new pointer.
-		if (!delayedUpload && LLGestureMgr::instance().isGestureActive(mItemUUID))
-		{
-			// gesture manager now owns the pointer
-			LLGestureMgr::instance().replaceGesture(mItemUUID, gesture, asset_id);
-
-			// replaceGesture may deactivate other gestures so let the
-			// inventory know.
-			gInventory.notifyObservers();
-		}
-		else
-		{
-			// we're done with this gesture
-			delete gesture;
-			gesture = NULL;
-		}
-
-		mDirty = FALSE;
-		// refresh will be called when callback
-		// if triggered when delayedUpload
-		if(!delayedUpload)
-		{
-			refresh();
-		}
-	}
+    // Copy the UI into a gesture
+    LLMultiGesture* gesture = createGesture();
+
+    // Serialize the gesture
+    S32 maxSize = gesture->getMaxSerialSize();
+    char* buffer = new char[maxSize];
+
+    LLDataPackerAsciiBuffer dp(buffer, maxSize);
+
+    bool ok = gesture->serialize(dp);
+
+    if (dp.getCurrentSize() > 1000)
+    {
+        LLNotificationsUtil::add("GestureSaveFailedTooManySteps");
+
+        delete gesture;
+        gesture = NULL;
+        return;
+    }
+    else if (!ok)
+    {
+        LLNotificationsUtil::add("GestureSaveFailedTryAgain");
+        delete gesture;
+        gesture = NULL;
+        return;
+    }
+
+    LLAssetID assetId;
+    LLPreview::onCommit();
+    bool delayedUpload(false);
+
+    LLViewerInventoryItem* item = (LLViewerInventoryItem*) getItem();
+    if (item)
+    {
+        const LLViewerRegion* region = gAgent.getRegion();
+        if (!region)
+        {
+            LL_WARNS() << "Not connected to a region, cannot save notecard." << LL_ENDL;
+            return;
+        }
+        std::string agent_url = region->getCapability("UpdateGestureAgentInventory");
+        std::string task_url = region->getCapability("UpdateGestureTaskInventory");
+
+        if (!agent_url.empty() && !task_url.empty())
+        {
+            std::string url;
+            LLResourceUploadInfo::ptr_t uploadInfo;
+
+            if (mObjectUUID.isNull() && !agent_url.empty())
+            {
+                //need to disable the preview floater so item
+                //isn't re-saved before new asset arrives
+                //fake out refresh.
+                item->setComplete(false);
+                refresh();
+                item->setComplete(true);
+
+                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_GESTURE, buffer,
+                    boost::bind(&LLPreviewGesture::finishInventoryUpload, _1, _2)));
+                url = agent_url;
+            }
+            else if (!mObjectUUID.isNull() && !task_url.empty())
+            {
+                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, NULL));
+                url = task_url;
+            }
+
+            if (!url.empty() && uploadInfo)
+            {
+                delayedUpload = true;
+
+                LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+            }
+
+        }
+        else if (gAssetStorage)
+        {
+            // Every save gets a new UUID.  Yup.
+            LLTransactionID tid;
+            tid.generate();
+            assetId = tid.makeAssetID(gAgent.getSecureSessionID());
+
+            LLVFile file(gVFS, assetId, LLAssetType::AT_GESTURE, LLVFile::APPEND);
+
+            S32 size = dp.getCurrentSize();
+            file.setMaxSize(size);
+            file.write((U8*)buffer, size);
+
+            LLLineEditor* descEditor = getChild<LLLineEditor>("desc");
+            LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid);
+            gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE);
+        }
+
+    }
+
+    // If this gesture is active, then we need to update the in-memory
+    // active map with the new pointer.
+    if (!delayedUpload && LLGestureMgr::instance().isGestureActive(mItemUUID))
+    {
+        // gesture manager now owns the pointer
+        LLGestureMgr::instance().replaceGesture(mItemUUID, gesture, assetId);
+
+        // replaceGesture may deactivate other gestures so let the
+        // inventory know.
+        gInventory.notifyObservers();
+    }
+    else
+    {
+        // we're done with this gesture
+        delete gesture;
+        gesture = NULL;
+    }
+
+    mDirty = false;
+    // refresh will be called when callback
+    // if triggered when delayedUpload
+    if(!delayedUpload)
+    {
+        refresh();
+    }
 
-	delete [] buffer;
-	buffer = NULL;
 }
 
 
diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h
index 7ce5706a0d9c36e4f825d4ff1e7077375908ae0f..3ba4f562952505e041100a5c23f905d6b920d3b3 100755
--- a/indra/newview/llpreviewgesture.h
+++ b/indra/newview/llpreviewgesture.h
@@ -132,6 +132,7 @@ class LLPreviewGesture : public LLPreview
 
 	static void onDonePreview(LLMultiGesture* gesture, void* data);
 
+    static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId);
 private:
 	// LLPreview contains mDescEditor
 	LLLineEditor*	mTriggerEditor;
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 9f88b0db5f7c792c60157da1320f62e899fd0a07..af56fe367e147e125c6ad3cbb632faf62ec05e18 100755
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -31,7 +31,6 @@
 #include "llinventory.h"
 
 #include "llagent.h"
-#include "llassetuploadresponders.h"
 #include "lldraghandle.h"
 #include "llviewerwindow.h"
 #include "llbutton.h"
@@ -56,6 +55,7 @@
 #include "llappviewer.h"		// app_abort_quit()
 #include "lllineeditor.h"
 #include "lluictrlfactory.h"
+#include "llviewerassetupload.h"
 
 ///----------------------------------------------------------------------------
 /// Class LLPreviewNotecard
@@ -232,7 +232,7 @@ void LLPreviewNotecard::loadAsset()
 			}
 			else
 			{
-				LLHost source_sim = LLHost::invalid;
+				LLHost source_sim = LLHost();
 				if (mObjectUUID.notNull())
 				{
 					LLViewerObject *objectp = gObjectList.findObject(mObjectUUID);
@@ -401,6 +401,35 @@ struct LLSaveNotecardInfo
 	}
 };
 
+void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId)
+{
+    // Update the UI with the new asset.
+    LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", LLSD(itemId));
+    if (nc)
+    {
+        // *HACK: we have to delete the asset in the VFS so
+        // that the viewer will redownload it. This is only
+        // really necessary if the asset had to be modified by
+        // the uploader, so this can be optimized away in some
+        // cases. A better design is to have a new uuid if the
+        // script actually changed the asset.
+        if (nc->hasEmbeddedInventory())
+        {
+            gVFS->removeFile(newAssetId, LLAssetType::AT_NOTECARD);
+        }
+        if (newItemId.isNull())
+        {
+            nc->setAssetId(newAssetId);
+            nc->refreshFromInventory();
+        }
+        else
+        {
+            nc->refreshFromInventory(newItemId);
+        }
+    }
+}
+
+
 bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
 {
 	LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
@@ -413,14 +442,6 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
 
 	if(!editor->isPristine())
 	{
-		// We need to update the asset information
-		LLTransactionID tid;
-		LLAssetID asset_id;
-		tid.generate();
-		asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-
-		LLVFile file(gVFS, asset_id, LLAssetType::AT_NOTECARD, LLVFile::APPEND);
-
 		std::string buffer;
 		if (!editor->exportBuffer(buffer))
 		{
@@ -429,52 +450,64 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
 
 		editor->makePristine();
 
-		S32 size = buffer.length() + 1;
-		file.setMaxSize(size);
-		file.write((U8*)buffer.c_str(), size);
-
 		const LLInventoryItem* item = getItem();
 		// save it out to database
-		if (item)
-		{			
-			const LLViewerRegion* region = gAgent.getRegion();
-			if (!region)
-			{
-				LL_WARNS() << "Not connected to a region, cannot save notecard." << LL_ENDL;
-				return false;
-			}
-			std::string agent_url = region->getCapability("UpdateNotecardAgentInventory");
-			std::string task_url = region->getCapability("UpdateNotecardTaskInventory");
-
-			if (mObjectUUID.isNull() && !agent_url.empty())
-			{
-				// Saving into agent inventory
-				mAssetStatus = PREVIEW_ASSET_LOADING;
-				setEnabled(FALSE);
-				LLSD body;
-				body["item_id"] = mItemUUID;
-				LL_INFOS() << "Saving notecard " << mItemUUID
-					<< " into agent inventory via " << agent_url << LL_ENDL;
-				LLHTTPClient::post(agent_url, body,
-					new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
-			}
-			else if (!mObjectUUID.isNull() && !task_url.empty())
-			{
-				// Saving into task inventory
-				mAssetStatus = PREVIEW_ASSET_LOADING;
-				setEnabled(FALSE);
-				LLSD body;
-				body["task_id"] = mObjectUUID;
-				body["item_id"] = mItemUUID;
-				LL_INFOS() << "Saving notecard " << mItemUUID << " into task "
-					<< mObjectUUID << " via " << task_url << LL_ENDL;
-				LLHTTPClient::post(task_url, body,
-					new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD));
-			}
+        if (item)
+        {
+            const LLViewerRegion* region = gAgent.getRegion();
+            if (!region)
+            {
+                LL_WARNS() << "Not connected to a region, cannot save notecard." << LL_ENDL;
+                return false;
+            }
+            std::string agent_url = region->getCapability("UpdateNotecardAgentInventory");
+            std::string task_url = region->getCapability("UpdateNotecardTaskInventory");
+
+            if (!agent_url.empty() && !task_url.empty())
+            {
+                std::string url;
+                LLResourceUploadInfo::ptr_t uploadInfo;
+
+                if (mObjectUUID.isNull() && !agent_url.empty())
+                {
+                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _2, _3)));
+                    url = agent_url;
+                }
+                else if (!mObjectUUID.isNull() && !task_url.empty())
+                {
+                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _3, LLUUID::null)));
+                    url = task_url;
+                }
+
+                if (!url.empty() && uploadInfo)
+                {
+                    mAssetStatus = PREVIEW_ASSET_LOADING;
+                    setEnabled(false);
+
+                    LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+                }
+
+            }
 			else if (gAssetStorage)
 			{
+                // We need to update the asset information
+                LLTransactionID tid;
+                LLAssetID asset_id;
+                tid.generate();
+                asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+                LLVFile file(gVFS, asset_id, LLAssetType::AT_NOTECARD, LLVFile::APPEND);
+
+
 				LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID,
 																tid, copyitem);
+
+                S32 size = buffer.length() + 1;
+                file.setMaxSize(size);
+                file.write((U8*)buffer.c_str(), size);
+
 				gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD,
 												&onSaveComplete,
 												(void*)info,
diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h
index 1cf08dedd609d433417238d7d77128ae9be4245b..ba571995f6d2b359b4c8e4668285f8cb0f09d8ac 100755
--- a/indra/newview/llpreviewnotecard.h
+++ b/indra/newview/llpreviewnotecard.h
@@ -95,6 +95,8 @@ class LLPreviewNotecard : public LLPreview
 	bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
 	bool handleConfirmDeleteDialog(const LLSD& notification, const LLSD& response);
 
+    static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId);
+
 protected:
 	LLViewerTextEditor* mEditor;
 	LLButton* mSaveBtn;
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 1bbb22416d6b114514a11967f3177269e0c4f140..5f029ca6a22aa44dbb234c7b1d0d8cf6f5dfe010 100755
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -29,7 +29,6 @@
 #include "llpreviewscript.h"
 
 #include "llassetstorage.h"
-#include "llassetuploadresponders.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
@@ -88,7 +87,7 @@
 #include "llfloatergotoline.h"
 #include "llexperiencecache.h"
 #include "llfloaterexperienceprofile.h"
-#include "llexperienceassociationresponder.h"
+#include "llviewerassetupload.h"
 
 const std::string HELLO_LSL =
 	"default\n"
@@ -118,26 +117,6 @@ static bool have_script_upload_cap(LLUUID& object_id)
 	return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty());
 }
 
-
-class ExperienceResponder : public LLHTTPClient::Responder
-{
-public:
-	ExperienceResponder(const LLHandle<LLLiveLSLEditor>& parent):mParent(parent)
-	{
-	}
-
-	LLHandle<LLLiveLSLEditor> mParent;
-
-	/*virtual*/ void httpSuccess()
-	{
-		LLLiveLSLEditor* parent = mParent.get();
-		if(!parent)
-			return;
-
-		parent->setExperienceIds(getContent()["experience_ids"]);		
-	}
-};
-
 /// ---------------------------------------------------------------------------
 /// LLLiveLSLFile
 /// ---------------------------------------------------------------------------
@@ -1346,7 +1325,7 @@ void LLLiveLSLEditor::buildExperienceList()
 			position = ADD_TOP;
 		}
 		
-		const LLSD& experience = LLExperienceCache::get(id);
+        const LLSD& experience = LLExperienceCache::instance().get(id);
 		if(experience.isUndefined())
 		{
 			mExperiences->add(getString("loading"), id, position);
@@ -1365,7 +1344,7 @@ void LLLiveLSLEditor::buildExperienceList()
 
 	if(!foundAssociated )
 	{
-		const LLSD& experience = LLExperienceCache::get(associated);
+        const LLSD& experience = LLExperienceCache::instance().get(associated);
 		if(experience.isDefined())
 		{
 			std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
@@ -1386,7 +1365,7 @@ void LLLiveLSLEditor::buildExperienceList()
 	if(last.notNull())
 	{
 		mExperiences->setEnabled(FALSE);
-		LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));  
+        LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));
 	}
 	else
 	{
@@ -1416,11 +1395,23 @@ void LLLiveLSLEditor::requestExperiences()
 		std::string lookup_url=region->getCapability("GetCreatorExperiences"); 
 		if(!lookup_url.empty())
 		{
-			LLHTTPClient::get(lookup_url, new ExperienceResponder(getDerivedHandle<LLLiveLSLEditor>()));
+            LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success =
+                boost::bind(&LLLiveLSLEditor::receiveExperienceIds, _1, getDerivedHandle<LLLiveLSLEditor>());
+
+            LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, success);
 		}
 	}
 }
 
+/*static*/ 
+void LLLiveLSLEditor::receiveExperienceIds(LLSD result, LLHandle<LLLiveLSLEditor> hparent)
+{
+    LLLiveLSLEditor* parent = hparent.get();
+    if (!parent)
+        return;
+
+    parent->setExperienceIds(result["experience_ids"]);
+}
 
 
 /// ---------------------------------------------------------------------------
@@ -1571,7 +1562,7 @@ void LLPreviewLSL::loadAsset()
 		if (gAgent.isGodlike() || (is_copyable && (is_modifiable || is_library)))
 		{
 			LLUUID* new_uuid = new LLUUID(mItemUUID);
-			gAssetStorage->getInvItemAsset(LLHost::invalid,
+			gAssetStorage->getInvItemAsset(LLHost(),
 										gAgent.getID(),
 										gAgent.getSessionID(),
 										item->getPermissions().getOwner(),
@@ -1641,62 +1632,74 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
 	self->saveIfNeeded();
 }
 
+/*static*/
+void LLPreviewLSL::finishedLSLUpload(LLUUID itemId, LLSD response)
+{
+    // Find our window and close it if requested.
+    LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", LLSD(itemId));
+    if (preview)
+    {
+        // Bytecode save completed
+        if (response["compiled"])
+        {
+            preview->callbackLSLCompileSucceeded();
+        }
+        else
+        {
+            preview->callbackLSLCompileFailed(response["errors"]);
+        }
+    }
+}
+
 // Save needs to compile the text in the buffer. If the compile
 // succeeds, then save both assets out to the database. If the compile
 // fails, go ahead and save the text anyway.
 void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
 {
-	// LL_INFOS() << "LLPreviewLSL::saveIfNeeded()" << LL_ENDL;
-	if(!mScriptEd->hasChanged())
-	{
-		return;
-	}
-
-	mPendingUploads = 0;
-	mScriptEd->mErrorList->deleteAllItems();
-	mScriptEd->mEditor->makePristine();
-
-	// save off asset into file
-	LLTransactionID tid;
-	tid.generate();
-	LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
-	std::string filename = filepath + ".lsl";
-
-	mScriptEd->writeToFile(filename);
-
-	if (sync)
-	{
-		mScriptEd->sync();
-	}
-
-	const LLInventoryItem *inv_item = getItem();
-	// save it out to asset server
-	std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
-	if(inv_item)
-	{
-		getWindow()->incBusyCount();
-		mPendingUploads++;
-		if (!url.empty())
-		{
-			uploadAssetViaCaps(url, filename, mItemUUID);
-		}
-		else if (gAssetStorage)
-		{
-			uploadAssetLegacy(filename, mItemUUID, tid);
-		}
-	}
-}
-
-void LLPreviewLSL::uploadAssetViaCaps(const std::string& url,
-									  const std::string& filename,
-									  const LLUUID& item_id)
-{
-	LL_INFOS() << "Update Agent Inventory via capability" << LL_ENDL;
-	LLSD body;
-	body["item_id"] = item_id;
-	body["target"] = "lsl2";
-	LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT));
+    if (!mScriptEd->hasChanged())
+    {
+        return;
+    }
+
+    mPendingUploads = 0;
+    mScriptEd->mErrorList->deleteAllItems();
+    mScriptEd->mEditor->makePristine();
+
+    if (sync)
+    {
+        mScriptEd->sync();
+    }
+
+    const LLInventoryItem *inv_item = getItem();
+    // save it out to asset server
+    std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
+    if(inv_item)
+    {
+        getWindow()->incBusyCount();
+        mPendingUploads++;
+        if (!url.empty())
+        {
+            std::string buffer(mScriptEd->mEditor->getText());
+            LLBufferedAssetUploadInfo::invnUploadFinish_f proc = boost::bind(&LLPreviewLSL::finishedLSLUpload, _1, _4);
+
+            LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mItemUUID, buffer, proc));
+
+            LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+        }
+        else if (gAssetStorage)
+        {
+            // save off asset into file
+            LLTransactionID tid;
+            tid.generate();
+            LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+            std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, asset_id.asString());
+            std::string filename = filepath + ".lsl";
+
+            mScriptEd->writeToFile(filename);
+
+            uploadAssetLegacy(filename, mItemUUID, tid);
+        }
+    }
 }
 
 void LLPreviewLSL::uploadAssetLegacy(const std::string& filename,
@@ -2035,8 +2038,9 @@ void LLLiveLSLEditor::loadAsset()
 
 			if(item)
 			{
-				ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
-				
+                LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(),
+                        boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
+
 				bool isGodlike = gAgent.isGodlike();
 				bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
 				mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE);
@@ -2321,6 +2325,33 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
 	mItem = new LLViewerInventoryItem(item);
 }
 
+
+/*static*/
+void LLLiveLSLEditor::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, bool isRunning)
+{
+    LLSD floater_key;
+    floater_key["taskid"] = taskId;
+    floater_key["itemid"] = itemId;
+
+    LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key);
+    if (preview)
+    {
+        preview->mItem->setAssetUUID(newAssetId);
+
+        // Bytecode save completed
+        if (response["compiled"])
+        {
+            preview->callbackLSLCompileSucceeded(taskId, itemId, isRunning);
+        }
+        else
+        {
+            preview->callbackLSLCompileFailed(response["errors"]);
+        }
+    }
+
+}
+
+
 // virtual
 void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
 {
@@ -2331,7 +2362,7 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
 		return;
 	}
 
-	if(mItem.isNull() || !mItem->isFinished())
+    if (mItem.isNull() || !mItem->isFinished())
 	{
 		// $NOTE: While the error message may not be exactly correct,
 		// it's pretty close.
@@ -2339,78 +2370,68 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
 		return;
 	}
 
-	// get the latest info about it. We used to be losing the script
-	// name on save, because the viewer object version of the item,
-	// and the editor version would get out of synch. Here's a good
-	// place to synch them back up.
-	LLInventoryItem* inv_item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
-	if(inv_item)
-	{
-		mItem->copyItem(inv_item);
-	}
-
-	// Don't need to save if we're pristine
-	if(!mScriptEd->hasChanged())
-	{
-		return;
-	}
-
-	mPendingUploads = 0;
-
-	// save the script
-	mScriptEd->enableSave(FALSE);
-	mScriptEd->mEditor->makePristine();
-	mScriptEd->mErrorList->deleteAllItems();
-
-	// set up the save on the local machine.
-	mScriptEd->mEditor->makePristine();
-	LLTransactionID tid;
-	tid.generate();
-	LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
-	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
-	std::string filename = llformat("%s.lsl", filepath.c_str());
-
-	mItem->setAssetUUID(asset_id);
-	mItem->setTransactionID(tid);
+    // get the latest info about it. We used to be losing the script
+    // name on save, because the viewer object version of the item,
+    // and the editor version would get out of synch. Here's a good
+    // place to synch them back up.
+    LLInventoryItem* inv_item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
+    if (inv_item)
+    {
+        mItem->copyItem(inv_item);
+    }
+
+    // Don't need to save if we're pristine
+    if(!mScriptEd->hasChanged())
+    {
+        return;
+    }
+
+    mPendingUploads = 0;
+
+    // save the script
+    mScriptEd->enableSave(FALSE);
+    mScriptEd->mEditor->makePristine();
+    mScriptEd->mErrorList->deleteAllItems();
+    mScriptEd->mEditor->makePristine();
+
+    if (sync)
+    {
+        mScriptEd->sync();
+    }
+    bool isRunning = getChild<LLCheckBoxCtrl>("running")->get();
+    getWindow()->incBusyCount();
+    mPendingUploads++;
+
+    std::string url = object->getRegion()->getCapability("UpdateScriptTask");
+
+    if (!url.empty())
+    {
+        std::string buffer(mScriptEd->mEditor->getText());
+        LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLLiveLSLEditor::finishLSLUpload, _1, _2, _3, _4, isRunning);
+
+        LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mObjectUUID, mItemUUID, 
+                monoChecked() ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, 
+                isRunning, mScriptEd->getAssociatedExperience(), buffer, proc));
+
+        LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+    }
+    else if (gAssetStorage)
+    {
+        // set up the save on the local machine.
+        LLTransactionID tid;
+        tid.generate();
+        LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+        std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, asset_id.asString());
+        std::string filename = llformat("%s.lsl", filepath.c_str());
+
+        mItem->setAssetUUID(asset_id);
+        mItem->setTransactionID(tid);
+
+        mScriptEd->writeToFile(filename);
+
+        uploadAssetLegacy(filename, object, tid, isRunning);
+    }
 
-	mScriptEd->writeToFile(filename);
-
-	if (sync)
-	{
-		mScriptEd->sync();
-	}
-	
-	// save it out to asset server
-	std::string url = object->getRegion()->getCapability("UpdateScriptTask");
-	getWindow()->incBusyCount();
-	mPendingUploads++;
-	BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
-	if (!url.empty())
-	{
-		uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running, mScriptEd->getAssociatedExperience());
-	}
-	else if (gAssetStorage)
-	{
-		uploadAssetLegacy(filename, object, tid, is_running);
-	}
-}
-
-void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
-										 const std::string& filename,
-										 const LLUUID& task_id,
-										 const LLUUID& item_id,
-										 BOOL is_running,
-										 const LLUUID& experience_public_id )
-{
-	LL_INFOS() << "Update Task Inventory via capability " << url << LL_ENDL;
-	LLSD body;
-	body["task_id"] = task_id;
-	body["item_id"] = item_id;
-	body["is_script_running"] = is_running;
-	body["target"] = monoChecked() ? "mono" : "lsl2";
-	body["experience"] = experience_public_id;
-	LLHTTPClient::post(url, body,
-		new LLUpdateTaskInventoryResponder(body, filename, LLAssetType::AT_LSL_TEXT));
 }
 
 void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename,
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index 5f65be73837770f13262c39119e36f827a7ec9e6..02f236a089553eae6bde61b8097f1b1eebc982e0 100755
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -203,9 +203,7 @@ class LLPreviewLSL : public LLScriptEdContainer
 
 	virtual void loadAsset();
 	/*virtual*/ void saveIfNeeded(bool sync = true);
-	void uploadAssetViaCaps(const std::string& url,
-							const std::string& filename, 
-							const LLUUID& item_id);
+
 	void uploadAssetLegacy(const std::string& filename,
 							const LLUUID& item_id,
 							const LLTransactionID& tid);
@@ -223,7 +221,7 @@ class LLPreviewLSL : public LLScriptEdContainer
 protected:
 	static void* createScriptEdPanel(void* userdata);
 
-
+    static void finishedLSLUpload(LLUUID itemId, LLSD response);
 protected:
 
 	// Can safely close only after both text and bytecode are uploaded
@@ -270,12 +268,6 @@ class LLLiveLSLEditor : public LLScriptEdContainer
 	virtual void loadAsset();
 	void loadAsset(BOOL is_new);
 	/*virtual*/ void saveIfNeeded(bool sync = true);
-	void uploadAssetViaCaps(const std::string& url,
-							const std::string& filename,
-							const LLUUID& task_id,
-							const LLUUID& item_id,
-							BOOL is_running,
-							const LLUUID& experience_public_id);
 	void uploadAssetLegacy(const std::string& filename,
 						   LLViewerObject* object,
 						   const LLTransactionID& tid,
@@ -303,6 +295,9 @@ class LLLiveLSLEditor : public LLScriptEdContainer
 
 	static void	onMonoCheckboxClicked(LLUICtrl*, void* userdata);
 
+    static void finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, bool isRunning);
+    static void receiveExperienceIds(LLSD result, LLHandle<LLLiveLSLEditor> parent);
+
 private:
 	bool				mIsNew;
 	//LLUUID mTransmitID;
diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp
index e92bf4590d1096d2a2ce2de4805f5da54169ff18..b663df4aae8f67a570e362cae2e762dd6eeb4b00 100755
--- a/indra/newview/llproductinforequest.cpp
+++ b/indra/newview/llproductinforequest.cpp
@@ -32,31 +32,10 @@
 #include "llagent.h"  // for gAgent
 #include "lltrans.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
-class LLProductInfoRequestResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLProductInfoRequestResponder);
-private:
-	//If we get back a normal response, handle it here
-	/* virtual */ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if (!content.isArray())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		LLProductInfoRequestManager::instance().setSkuDescriptions(getContent());
-	}
-
-	//If we get back an error (not found, etc...), handle it here
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
-};
-
-LLProductInfoRequestManager::LLProductInfoRequestManager() : mSkuDescriptions()
+LLProductInfoRequestManager::LLProductInfoRequestManager(): 
+    mSkuDescriptions()
 {
 }
 
@@ -65,15 +44,11 @@ void LLProductInfoRequestManager::initSingleton()
 	std::string url = gAgent.getRegion()->getCapability("ProductInfoRequest");
 	if (!url.empty())
 	{
-		LLHTTPClient::get(url, new LLProductInfoRequestResponder());
+        LLCoros::instance().launch("LLProductInfoRequestManager::getLandDescriptionsCoro",
+            boost::bind(&LLProductInfoRequestManager::getLandDescriptionsCoro, this, url));
 	}
 }
 
-void LLProductInfoRequestManager::setSkuDescriptions(const LLSD& content)
-{
-	mSkuDescriptions = content;
-}
-
 std::string LLProductInfoRequestManager::getDescriptionForSku(const std::string& sku)
 {
 	// The description LLSD is an array of maps; each array entry
@@ -90,3 +65,31 @@ std::string LLProductInfoRequestManager::getDescriptionForSku(const std::string&
 	}
 	return LLTrans::getString("land_type_unknown");
 }
+
+void LLProductInfoRequestManager::getLandDescriptionsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        return;
+    }
+
+    if (result.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT) &&
+        result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT].isArray())
+    {
+        mSkuDescriptions = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
+    }
+    else
+    {
+        LL_WARNS() << "Land SKU description response is malformed" << LL_ENDL;
+    }
+}
diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h
index fe8f7093b0452621f83c0c2d3311c64364c3a6a8..75dbf220d17cdf140bba4aea684e9b3a101293a7 100755
--- a/indra/newview/llproductinforequest.h
+++ b/indra/newview/llproductinforequest.h
@@ -28,27 +28,29 @@
 #ifndef LL_LLPRODUCTINFOREQUEST_H
 #define LL_LLPRODUCTINFOREQUEST_H
 
-#include "llhttpclient.h"
 #include "llmemory.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
-/* 
- This is a singleton to manage a cache of information about land types.
- The land system provides a capability to get information about the
- set of possible land sku, name, and description information.
- We use description in the UI, but the sku is provided in the various
- messages; this tool provides translation between the systems.
+/** 
+ * This is a singleton to manage a cache of information about land types.
+ * The land system provides a capability to get information about the
+ * set of possible land sku, name, and description information.
+ * We use description in the UI, but the sku is provided in the various
+ * messages; this tool provides translation between the systems.
  */
-
 class LLProductInfoRequestManager : public LLSingleton<LLProductInfoRequestManager>
 {
 public:
 	LLProductInfoRequestManager();
-	void setSkuDescriptions(const LLSD& content);
 	std::string getDescriptionForSku(const std::string& sku);
+
 private:
 	friend class LLSingleton<LLProductInfoRequestManager>;	
 	/* virtual */ void initSingleton();
-	LLSD mSkuDescriptions;
+
+    void getLandDescriptionsCoro(std::string url);
+    LLSD mSkuDescriptions;
 };
 
 #endif // LL_LLPRODUCTINFOREQUEST_H
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 1257ee7f9492870b42f2afca006f28d7c11b02ff..c17b86783d139ab1ded51ab9ee76e013f55a34e5 100755
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -175,6 +175,10 @@ void LLProgressView::setStartupComplete()
 
 void LLProgressView::setVisible(BOOL visible)
 {
+    if (!visible && mFadeFromLoginTimer.getStarted())
+    {
+        mFadeFromLoginTimer.stop();
+    }
 	// hiding progress view
 	if (getVisible() && !visible)
 	{
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 29dcc12f9e315f3e96fd70c5fc3ab36773731595..055ccd5818545c40f57c997141be639156cc428a 100755
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -31,55 +31,16 @@
 #include "message.h"
 
 #include "llpanel.h"
-#include "llhttpclient.h"
 #include "llsdserialize.h"
 #include "llurlentry.h"
 #include "llviewerregion.h"
 #include "llview.h"
-
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "llregionhandle.h"
 #include "llagent.h"
 #include "llremoteparcelrequest.h"
-
-
-LLRemoteParcelRequestResponder::LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle)
-	 : mObserverHandle(observer_handle)
-{}
-
-//If we get back a normal response, handle it here
-//virtual
-void LLRemoteParcelRequestResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap() || !content.has("parcel_id"))
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	LLUUID parcel_id = getContent()["parcel_id"];
-
-	// Panel inspecting the information may be closed and destroyed
-	// before this response is received.
-	LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
-	if (observer)
-	{
-		observer->setParcelID(parcel_id);
-	}
-}
-
-//If we get back an error (not found, etc...), handle it here
-//virtual
-void LLRemoteParcelRequestResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-
-	// Panel inspecting the information may be closed and destroyed
-	// before this response is received.
-	LLRemoteParcelInfoObserver* observer = mObserverHandle.get();
-	if (observer)
-	{
-		observer->setErrorStatus(getStatus(), getReason());
-	}
-}
+#include "llcorehttputil.h"
 
 void LLRemoteParcelInfoProcessor::addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
 {
@@ -200,3 +161,64 @@ void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id)
 	msg->addUUID("ParcelID", parcel_id);
 	gAgent.sendReliableMessage();
 }
+
+bool LLRemoteParcelInfoProcessor::requestRegionParcelInfo(const std::string &url, 
+    const LLUUID &regionId, const LLVector3 &regionPos, const LLVector3d&globalPos,
+    LLHandle<LLRemoteParcelInfoObserver> observerHandle)
+{
+
+    if (!url.empty())
+    {
+        LLCoros::instance().launch("LLRemoteParcelInfoProcessor::regionParcelInfoCoro",
+            boost::bind(&LLRemoteParcelInfoProcessor::regionParcelInfoCoro, this, url,
+            regionId, regionPos, globalPos, observerHandle));
+        return true;
+    }
+
+    return false;
+}
+
+void LLRemoteParcelInfoProcessor::regionParcelInfoCoro(std::string url, 
+    LLUUID regionId, LLVector3 posRegion, LLVector3d posGlobal, 
+    LLHandle<LLRemoteParcelInfoObserver> observerHandle)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("RemoteParcelRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD bodyData;
+
+    bodyData["location"] = ll_sd_from_vector3(posRegion);
+    if (!regionId.isNull())
+    {
+        bodyData["region_id"] = regionId;
+    }
+    if (!posGlobal.isExactlyZero())
+    {
+        U64 regionHandle = to_region_handle(posGlobal);
+        bodyData["region_handle"] = ll_sd_from_U64(regionHandle);
+    }
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, bodyData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    LLRemoteParcelInfoObserver* observer = observerHandle.get();
+    // Panel inspecting the information may be closed and destroyed
+    // before this response is received.
+    if (!observer)
+        return;
+
+    if (!status)
+    {
+        observer->setErrorStatus(status.getStatus(), status.getMessage());
+    }
+    else 
+    {
+        LLUUID parcel_id = result["parcel_id"];
+        observer->setParcelID(parcel_id);
+    }
+
+}
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index 35348b69ffabb6de663366d2e0f62248928fb36e..cb5af50c5f083e737a7f5aab4a693b18fa466794 100755
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -29,29 +29,14 @@
 #ifndef LL_LLREMOTEPARCELREQUEST_H
 #define LL_LLREMOTEPARCELREQUEST_H
 
-#include "llhttpclient.h"
 #include "llhandle.h"
 #include "llsingleton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLMessageSystem;
 class LLRemoteParcelInfoObserver;
 
-class LLRemoteParcelRequestResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLRemoteParcelRequestResponder);
-public:
-	LLRemoteParcelRequestResponder(LLHandle<LLRemoteParcelInfoObserver> observer_handle);
-
-private:
-	//If we get back a normal response, handle it here
-	/*virtual*/ void httpSuccess();
-
-	//If we get back an error (not found, etc...), handle it here
-	/*virtual*/ void httpFailure();
-
-	LLHandle<LLRemoteParcelInfoObserver> mObserverHandle;
-};
-
 struct LLParcelData
 {
 	LLUUID		parcel_id;
@@ -99,9 +84,14 @@ class LLRemoteParcelInfoProcessor : public LLSingleton<LLRemoteParcelInfoProcess
 
 	static void processParcelInfoReply(LLMessageSystem* msg, void**);
 
+    bool requestRegionParcelInfo(const std::string &url, const LLUUID &regionId, 
+        const LLVector3 &regionPos, const LLVector3d& globalPos, LLHandle<LLRemoteParcelInfoObserver> observerHandle);
+
 private:
 	typedef std::multimap<LLUUID, LLHandle<LLRemoteParcelInfoObserver> > observer_multimap_t;
 	observer_multimap_t mObservers;
+
+    void regionParcelInfoCoro(std::string url, LLUUID regionId, LLVector3 posRegion, LLVector3d posGlobal, LLHandle<LLRemoteParcelInfoObserver> observerHandle);
 };
 
 #endif // LL_LLREMOTEPARCELREQUEST_H
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 43bb7b15965a6308df2ff7fac2777b280534ec04..4f9f83b6f26364dbec03a1269a4091c5441f6d25 100755
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -32,7 +32,6 @@
 #include <openssl/evp.h>
 #include <openssl/err.h>
 #include <map>
-#include "llhttpclient.h"
 
 
 
@@ -99,46 +98,6 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
 	return s << (std::string)cred;
 }
 
-	
-// secapiSSLCertVerifyCallback
-// basic callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-// not initialized in the above initialization function, due to unit tests
-// see llappviewer
-
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
-{
-	LLURLRequest *req = (LLURLRequest *)param;
-	LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
-	LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
-	LLSD validation_params = LLSD::emptyMap();
-	LLURI uri(req->getURL());
-	validation_params[CERT_HOSTNAME] = uri.hostName();
-	try
-	{
-		// we rely on libcurl to validate the hostname, as libcurl does more extensive validation
-		// leaving our hostname validation call mechanism for future additions with respect to
-		// OS native (Mac keyring, windows CAPI) validation.
-		store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
-	}
-	catch (LLCertValidationTrustException& cert_exception)
-	{
-		LL_WARNS("AppInit") << "Cert not trusted: " << cert_exception.getMessage() << LL_ENDL;
-		return 0;		
-	}
-	catch (LLCertException& cert_exception)
-	{
-		LL_WARNS("AppInit") << "cert error " << cert_exception.getMessage() << LL_ENDL;
-		return 0;
-	}
-	catch (...)
-	{
-		LL_WARNS("AppInit") << "cert error " << LL_ENDL;
-		return 0;
-	}
-	return 1;
-}
-
 LLSD LLCredential::getLoginParams()
 {
 	LLSD result = LLSD::emptyMap();
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index c01d318f56d5750a22bf81b568fa9e6ab8dc48fb..6fe3ee31cf0369b7d8ba12424ce941868a9aef6d 100755
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -489,7 +489,4 @@ void registerSecHandler(const std::string& handler_type,
 extern LLPointer<LLSecAPIHandler> gSecAPIHandler;
 
 
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
-
-
 #endif // LL_SECAPI_H
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 0e23e2ad10ae20294f8617b293494f3dcc2119cc..67ac87542838a9438e0fdb9f608ecbcc22042b95 100755
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -37,7 +37,6 @@
 #include "llfloatersidepanelcontainer.h"
 #include "llfoldertype.h"
 #include "llfolderview.h"
-#include "llhttpclient.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
 #include "llinventorymodel.h"
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index a7cfc173af998ff209b9eb44f9c44ba890974bbe..12cbff888d39cb7c1c916059b07342ddf72dbea1 100755
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -44,7 +44,6 @@
 #include "llviewercontrol.h"
 #include "llviewerinventory.h"
 #include "llviewerobjectlist.h"
-#include "llexperienceassociationresponder.h"
 #include "llexperiencecache.h"
 #include "lltrans.h"
 
@@ -328,7 +327,9 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
         LLTextBox* tb = getChild<LLTextBox>("LabelItemExperience");
         tb->setText(getString("loading_experience"));
         tb->setVisible(TRUE);
-        ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle<LLSidepanelItemInfo>(), _1));
+
+        LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), 
+            boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle<LLSidepanelItemInfo>(), _1));
     }
     
 	//////////////////////
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 0ae8a338e08f5c3f1ad4f219bf475f53ee1dede9..8fb3340db0f0943438f8718e5596e83f6ca02254 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -1004,21 +1004,18 @@ void LLSnapshotLivePreview::saveTexture()
 		LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
 		std::string who_took_it;
 		LLAgentUI::buildFullname(who_took_it);
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
 		S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-		void *userdata = NULL;
-		upload_new_resource(tid,	// tid
-			LLAssetType::AT_TEXTURE,
-			"Snapshot : " + pos_string,
-			"Taken by " + who_took_it + " at " + pos_string,
-			0,
-			LLFolderType::FT_SNAPSHOT_CATEGORY,
-			LLInventoryType::IT_SNAPSHOT,
-			PERM_ALL,  // Note: Snapshots to inventory is a special case of content upload
-			LLFloaterPerms::getGroupPerms("Uploads"), // that is more permissive than other uploads
-			LLFloaterPerms::getEveryonePerms("Uploads"),
-			"Snapshot : " + pos_string,
-			callback, expected_upload_cost, userdata);
+        std::string name = "Snapshot: " + pos_string;
+        std::string desc = "Taken by " + who_took_it + " at " + pos_string;
+
+        LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
+            tid, LLAssetType::AT_TEXTURE, name, desc, 0,
+            LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT,
+            PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
+            expected_upload_cost));
+
+        upload_new_resource(assetUploadInfo);
+
 		gViewerWindow->playSnapshotAnimAndSound();
 	}
 	else
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 7867e1573ca9c57cf32e96962d7b5d4d4ab6dd30..974029254faded0cbfbea9737dd18d5dcde511bb 100755
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -34,11 +34,11 @@
 #include "llgroupmgr.h"
 #include "llsdutil.h"
 #include "lluicolortable.h"
-#include "llhttpclient.h"
 #include "llviewerobjectlist.h"
 #include "llviewerregion.h"
 #include "llvoavatar.h"
 #include "llworld.h"
+#include "llcorehttputil.h"
 
 extern LLControlGroup gSavedSettings;
 
@@ -264,49 +264,6 @@ bool LLSpeakersDelayActionsStorage::isTimerStarted(const LLUUID& speaker_id)
 	return (mActionTimersMap.size() > 0) && (mActionTimersMap.find(speaker_id) != mActionTimersMap.end());
 }
 
-//
-// ModerationResponder
-//
-
-class ModerationResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(ModerationResponder);
-public:
-	ModerationResponder(const LLUUID& session_id)
-	{
-		mSessionID = session_id;
-	}
-	
-protected:
-	virtual void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-		
-		if ( gIMMgr )
-		{
-			//403 == you're not a mod
-			//should be disabled if you're not a moderator
-			if ( HTTP_FORBIDDEN == getStatus() )
-			{
-				gIMMgr->showSessionEventError(
-											  "mute",
-											  "not_a_mod_error",
-											  mSessionID);
-			}
-			else
-			{
-				gIMMgr->showSessionEventError(
-											  "mute",
-											  "generic_request_error",
-											  mSessionID);
-			}
-		}
-	}
-	
-private:
-	LLUUID mSessionID;
-};
-
 //
 // LLSpeakerMgr
 //
@@ -883,7 +840,8 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
 	//current value represents ability to type, so invert
 	data["params"]["mute_info"]["text"] = !speakerp->mModeratorMutedText;
 
-	LLHTTPClient::post(url, data, new ModerationResponder(getSessionID()));
+    LLCoros::instance().launch("LLIMSpeakerMgr::moderationActionCoro",
+        boost::bind(&LLIMSpeakerMgr::moderationActionCoro, this, url, data));
 }
 
 void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)
@@ -907,10 +865,50 @@ void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmu
 	data["params"]["mute_info"] = LLSD::emptyMap();
 	data["params"]["mute_info"]["voice"] = !unmute;
 
-	LLHTTPClient::post(
-		url,
-		data,
-		new ModerationResponder(getSessionID()));
+    LLCoros::instance().launch("LLIMSpeakerMgr::moderationActionCoro",
+        boost::bind(&LLIMSpeakerMgr::moderationActionCoro, this, url, data));
+}
+
+void LLIMSpeakerMgr::moderationActionCoro(std::string url, LLSD action)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("moderationActionCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+
+    LLUUID sessionId = action["session-id"];
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, action, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        if (gIMMgr)
+        {
+            //403 == you're not a mod
+            //should be disabled if you're not a moderator
+            if (status == LLCore::HttpStatus(HTTP_FORBIDDEN))
+            {
+                gIMMgr->showSessionEventError(
+                    "mute",
+                    "not_a_mod_error",
+                    sessionId);
+            }
+            else
+            {
+                gIMMgr->showSessionEventError(
+                    "mute",
+                    "generic_request_error",
+                    sessionId);
+            }
+        }
+        return;
+    }
 }
 
 void LLIMSpeakerMgr::moderateVoiceAllParticipants( bool unmute_everyone )
@@ -949,7 +947,8 @@ void LLIMSpeakerMgr::moderateVoiceSession(const LLUUID& session_id, bool disallo
 	data["params"]["update_info"]["moderated_mode"] = LLSD::emptyMap();
 	data["params"]["update_info"]["moderated_mode"]["voice"] = disallow_voice;
 
-	LLHTTPClient::post(url, data, new ModerationResponder(session_id));
+    LLCoros::instance().launch("LLIMSpeakerMgr::moderationActionCoro",
+        boost::bind(&LLIMSpeakerMgr::moderationActionCoro, this, url, data));
 }
 
 void LLIMSpeakerMgr::forceVoiceModeratedMode(bool should_be_muted)
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 0e691841250ff23a78fa225d4d84dcfe7bc0a2fc..5cff70f37767cdf42aace17853c62923a548f2b0 100755
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -30,6 +30,8 @@
 #include "llevent.h"
 #include "lleventtimer.h"
 #include "llvoicechannel.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLSpeakerMgr;
 
@@ -333,6 +335,8 @@ class LLIMSpeakerMgr : public LLSpeakerMgr
 	 */
 	void forceVoiceModeratedMode(bool should_be_muted);
 
+    void moderationActionCoro(std::string url, LLSD action);
+
 };
 
 class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d2050aec3e6410e57901464fa5a265243e4fd3b9..2c6b9d14bfe60236a1992ce0b900bd296d430a4d 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -46,7 +46,6 @@
 #include "llaudioengine_openal.h"
 #endif
 
-#include "llares.h"
 #include "llavatarnamecache.h"
 #include "llexperiencecache.h"
 #include "lllandmark.h"
@@ -56,7 +55,6 @@
 #include "llerrorcontrol.h"
 #include "llfloaterreg.h"
 #include "llfocusmgr.h"
-#include "llhttpsender.h"
 #include "llfloaterimsession.h"
 #include "lllocationhistory.h"
 #include "llimageworker.h"
@@ -113,7 +111,6 @@
 #include "llgroupmgr.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
-#include "llhttpclient.h"
 #include "llimagebmp.h"
 #include "llinventorybridge.h"
 #include "llinventorymodel.h"
@@ -292,20 +289,6 @@ void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is
 // local classes
 //
 
-namespace
-{
-	class LLNullHTTPSender : public LLHTTPSender
-	{
-		virtual void send(const LLHost& host, 
-						  const std::string& message, const LLSD& body, 
-						  LLHTTPClient::ResponderPtr response) const
-		{
-			LL_WARNS("AppInit") << " attemped to send " << message << " to " << host
-					<< " with null sender" << LL_ENDL;
-		}
-	};
-}
-
 void update_texture_fetch()
 {
 	LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
@@ -460,13 +443,6 @@ bool idle_startup()
 		// Load the throttle settings
 		gViewerThrottle.load();
 
-		if (ll_init_ares() == NULL || !gAres->isInitialized())
-		{
-			std::string diagnostic = "Could not start address resolution system";
-			LL_WARNS("AppInit") << diagnostic << LL_ENDL;
-			LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
-		}
-		
 		//
 		// Initialize messaging system
 		//
@@ -511,8 +487,6 @@ bool idle_startup()
 			    port = gSavedSettings.getU32("ConnectionPort");
 			  }
 
-			LLHTTPSender::setDefaultSender(new LLNullHTTPSender());
-
 			// TODO parameterize 
 			const F32 circuit_heartbeat_interval = 5;
 			const F32 circuit_timeout = 100;
@@ -754,12 +728,9 @@ bool idle_startup()
 		if (gLoginMenuBarView == NULL)
 		{
 			LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL;
-			display_startup();
 			initialize_edit_menu();
 			initialize_spellcheck_menu();
-			display_startup();
 			init_menus();
-			display_startup();
 		}
 
 		if (show_connect_box)
@@ -771,23 +742,17 @@ bool idle_startup()
 			if (gUserCredential.isNull())                                                                          
 			{                                                  
 				LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL;
-				display_startup();
 				gUserCredential = gLoginHandler.initializeLoginInfo();                 
-				display_startup();
 			}     
 			// Make sure the process dialog doesn't hide things
-			display_startup();
 			gViewerWindow->setShowProgress(FALSE);
-			display_startup();
 			// Show the login dialog
 			login_show();
-			display_startup();
 			// connect dialog is already shown, so fill in the names
 			if (gUserCredential.notNull())
 			{
 				LLPanelLogin::setFields( gUserCredential, gRememberPassword);
 			}
-			display_startup();
 			LLPanelLogin::giveFocus();
 
 			// MAINT-3231 Show first run dialog only for Desura viewer
@@ -813,22 +778,15 @@ bool idle_startup()
 			LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
 		}
 
-		display_startup();
 		gViewerWindow->setNormalControlsVisible( FALSE );	
-		display_startup();
 		gLoginMenuBarView->setVisible( TRUE );
-		display_startup();
 		gLoginMenuBarView->setEnabled( TRUE );
-		display_startup();
 		show_debug_menus();
-		display_startup();
 
 		// Hide the splash screen
 		LLSplashScreen::hide();
-		display_startup();
 		// Push our window frontmost
 		gViewerWindow->getWindow()->show();
-		display_startup();
 
 		// DEV-16927.  The following code removes errant keystrokes that happen while the window is being 
 		// first made visible.
@@ -836,9 +794,9 @@ bool idle_startup()
 		MSG msg;
 		while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
 		{ }
-		display_startup();
 #endif
-		timeout.reset();
+        display_startup();
+        timeout.reset();
 		return FALSE;
 	}
 
@@ -2777,8 +2735,6 @@ void reset_login()
 	gAgent.cleanup();
 	LLWorld::getInstance()->destroyClass();
 
-	LLStartUp::setStartupState( STATE_LOGIN_SHOW );
-
 	if ( gViewerWindow )
 	{	// Hide menus and normal buttons
 		gViewerWindow->setNormalControlsVisible( FALSE );
@@ -2788,6 +2744,7 @@ void reset_login()
 
 	// Hide any other stuff
 	LLFloaterReg::hideVisibleInstances();
+    LLStartUp::setStartupState( STATE_BROWSER_INIT );
 }
 
 //---------------------------------------------------------------------------
@@ -2837,9 +2794,11 @@ void LLStartUp::initNameCache()
 
 
 void LLStartUp::initExperiences()
-{
-	LLAppViewer::instance()->loadExperienceCache();
-	LLExperienceCache::initClass();
+{   
+    // Should trigger loading the cache.
+    LLExperienceCache::instance().setCapabilityQuery(
+        boost::bind(&LLAgent::getRegionCapability, &gAgent, _1));
+
 	LLExperienceLog::instance().initialize();
 }
 
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp
index 802dff1ead9780710f3594cc36d4c56832f0f74b..9e54c521b59c320ba501c2dbf166eb6dd1c67f0b 100644
--- a/indra/newview/llsyntaxid.cpp
+++ b/indra/newview/llsyntaxid.cpp
@@ -31,69 +31,10 @@
 #include "llsyntaxid.h"
 #include "llagent.h"
 #include "llappviewer.h"
-#include "llhttpclient.h"
 #include "llsdserialize.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
-//-----------------------------------------------------------------------------
-// fetchKeywordsFileResponder
-//-----------------------------------------------------------------------------
-class fetchKeywordsFileResponder : public LLHTTPClient::Responder
-{
-public:
-	fetchKeywordsFileResponder(const std::string& filespec)
-	: mFileSpec(filespec)
-	{
-		LL_DEBUGS("SyntaxLSL") << "Instantiating with file saving to: '" << filespec << "'" << LL_ENDL;
-	}
-
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS("SyntaxLSL") << "failed to fetch syntax file [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
-	}
-
-	/* virtual */ void httpSuccess()
-	{
-		// Continue only if a valid LLSD object was returned.
-		const LLSD& content = getContent();
-		if (content.isMap())
-		{
-			if (LLSyntaxIdLSL::getInstance()->isSupportedVersion(content))
-			{
-				LLSyntaxIdLSL::getInstance()->setKeywordsXml(content);
-
-				cacheFile(content);
-				LLSyntaxIdLSL::getInstance()->handleFileFetched(mFileSpec);
-			}
-			else
-			{
-				LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
-			}
-		}
-		else
-		{
-			LL_WARNS("SyntaxLSL") << "Syntax file '" << mFileSpec << "' contains invalid LLSD." << LL_ENDL;
-		}
-	}
-
-	void cacheFile(const LLSD& content_ref)
-	{
-		std::stringstream str;
-		LLSDSerialize::toXML(content_ref, str);
-		const std::string xml = str.str();
-
-		// save the str to disk, usually to the cache.
-		llofstream file(mFileSpec.c_str(), std::ios_base::out);
-		file.write(xml.c_str(), str.str().size());
-		file.close();
-
-		LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << mFileSpec << "'" << LL_ENDL;
-	}
-	
-private:
-	std::string mFileSpec;
-};
-	
 //-----------------------------------------------------------------------------
 // LLSyntaxIdLSL
 //-----------------------------------------------------------------------------
@@ -166,13 +107,72 @@ bool LLSyntaxIdLSL::syntaxIdChanged()
 //-----------------------------------------------------------------------------
 void LLSyntaxIdLSL::fetchKeywordsFile(const std::string& filespec)
 {
-	mInflightFetches.push_back(filespec);
-	LLHTTPClient::get(mCapabilityURL,
-					  new fetchKeywordsFileResponder(filespec),
-					  LLSD(), 30.f);
+    LLCoros::instance().launch("LLSyntaxIdLSL::fetchKeywordsFileCoro",
+        boost::bind(&LLSyntaxIdLSL::fetchKeywordsFileCoro, this, mCapabilityURL, filespec));
 	LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is: " << mCapabilityURL << ". Filename to use is: '" << filespec << "'." << LL_ENDL;
 }
 
+//-----------------------------------------------------------------------------
+// fetchKeywordsFileCoro
+//-----------------------------------------------------------------------------
+void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    std::pair<std::set<std::string>::iterator, bool> insrt = mInflightFetches.insert(fileSpec);
+    if (!insrt.second)
+    {
+        LL_WARNS("SyntaxLSL") << "Already downloading keyword file called \"" << fileSpec << "\"." << LL_ENDL;
+        return;
+    }
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    mInflightFetches.erase(fileSpec);
+
+    if (!status)
+    {
+        LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file \"" << fileSpec << "\"" << LL_ENDL;
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+    if (isSupportedVersion(result))
+    {
+        setKeywordsXml(result);
+        cacheFile(fileSpec, result);
+        loadKeywordsIntoLLSD();
+    }
+    else
+    {
+        LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
+    }
+
+}
+
+//-----------------------------------------------------------------------------
+// cacheFile
+//-----------------------------------------------------------------------------
+void LLSyntaxIdLSL::cacheFile(const std::string &fileSpec, const LLSD& content_ref)
+{
+    std::stringstream str;
+    LLSDSerialize::toXML(content_ref, str);
+    const std::string xml = str.str();
+
+    // save the str to disk, usually to the cache.
+    llofstream file(fileSpec.c_str(), std::ios_base::out);
+    file.write(xml.c_str(), str.str().size());
+    file.close();
+
+    LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << fileSpec << "'" << LL_ENDL;
+}
 
 //-----------------------------------------------------------------------------
 // initialize
@@ -260,8 +260,8 @@ void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD()
 // loadKeywordsFileIntoLLSD
 //-----------------------------------------------------------------------------
 /**
- * @brief	Load xml serialised LLSD
- * @desc	Opens the specified filespec and attempts to deserialise the
+ * @brief	Load xml serialized LLSD
+ * @desc	Opens the specified filespec and attempts to deserializes the
  *			contained data to the specified LLSD object. indicate success/failure with
  *			sLoaded/sLoadFailed members.
  */
@@ -276,7 +276,7 @@ void LLSyntaxIdLSL::loadKeywordsIntoLLSD()
 		{
 			if (isSupportedVersion(content))
 			{
-				LL_DEBUGS("SyntaxLSL") << "Deserialised: " << mFullFileSpec << LL_ENDL;
+				LL_DEBUGS("SyntaxLSL") << "Deserialized: " << mFullFileSpec << LL_ENDL;
 			}
 			else
 			{
@@ -317,12 +317,6 @@ void LLSyntaxIdLSL::handleCapsReceived(const LLUUID& region_uuid)
 	}
 }
 
-void LLSyntaxIdLSL::handleFileFetched(const std::string& filepath)
-{
-	mInflightFetches.remove(filepath);
-	loadKeywordsIntoLLSD();
-}
-
 boost::signals2::connection LLSyntaxIdLSL::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
 {
 	return mSyntaxIDChangedSignal.connect(cb);
diff --git a/indra/newview/llsyntaxid.h b/indra/newview/llsyntaxid.h
index 504fb0997e1dda391186864920c4693acb1c4000..0afa6dc04ba2868e21f7600351991fea1a0c83ae 100644
--- a/indra/newview/llsyntaxid.h
+++ b/indra/newview/llsyntaxid.h
@@ -31,6 +31,8 @@
 #include "llviewerprecompiledheaders.h"
 
 #include "llsingleton.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class fetchKeywordsFileResponder;
 
@@ -40,7 +42,7 @@ class LLSyntaxIdLSL : public LLSingleton<LLSyntaxIdLSL>
 	friend class fetchKeywordsFileResponder;
 	
 private:
-	std::list<std::string> mInflightFetches;
+    std::set<std::string> mInflightFetches;
 	typedef boost::signals2::signal<void()> syntax_id_changed_signal_t;
 	syntax_id_changed_signal_t mSyntaxIDChangedSignal;
 	boost::signals2::connection mRegionChangedCallback;
@@ -49,13 +51,15 @@ class LLSyntaxIdLSL : public LLSingleton<LLSyntaxIdLSL>
 	bool	isSupportedVersion(const LLSD& content);
 	void	handleRegionChanged();
 	void	handleCapsReceived(const LLUUID& region_uuid);
-	void	handleFileFetched(const std::string& filepath);
 	void	setKeywordsXml(const LLSD& content) { mKeywordsXml = content; };
 	void	buildFullFileSpec();
 	void	fetchKeywordsFile(const std::string& filespec);
 	void	loadDefaultKeywordsIntoLLSD();
 	void	loadKeywordsIntoLLSD();
-	
+
+    void    fetchKeywordsFileCoro(std::string url, std::string fileSpec);
+    void    cacheFile(const std::string &fileSpec, const LLSD& content_ref);
+
 	std::string		mCapabilityURL;
 	std::string		mFullFileSpec;
 	ELLPath			mFilePath;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index fab4203ec3199faaa7fd364c576b35088204be58..30d90431eaa3476aed1a6c873a2bbec821f8ee5b 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -35,7 +35,6 @@
 #include "lltexturefetch.h"
 
 #include "lldir.h"
-#include "llhttpclient.h"
 #include "llhttpconstants.h"
 #include "llimage.h"
 #include "llimagej2c.h"
@@ -1329,11 +1328,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 		static LLCachedControl<bool> use_http(gSavedSettings, "ImagePipelineUseHTTP", true);
 
-// 		if (mHost != LLHost::invalid) get_url = false;
+// 		if (mHost.isInvalid()) get_url = false;
 		if ( use_http && mCanUseHTTP && mUrl.empty())//get http url.
 		{
 			LLViewerRegion* region = NULL;
-			if (mHost == LLHost::invalid)
+			if (mHost.isInvalid())
 				region = gAgent.getRegion();
 			else
 				region = LLWorld::getInstance()->getRegion(mHost);
@@ -1558,7 +1557,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
 
 		// Will call callbackHttpGet when curl request completes
 		// Only server bake images use the returned headers currently, for getting retry-after field.
-		LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
+		LLCore::HttpOptions::ptr_t options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
 		if (disable_range_req)
 		{
 			// 'Range:' requests may be disabled in which case all HTTP
@@ -2510,11 +2509,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mTotalHTTPRequests(0),
 	  mQAMode(qa_mode),
 	  mHttpRequest(NULL),
-	  mHttpOptions(NULL),
-	  mHttpOptionsWithHeaders(NULL),
-	  mHttpHeaders(NULL),
+	  mHttpOptions(),
+	  mHttpOptionsWithHeaders(),
+	  mHttpHeaders(),
 	  mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
-	  mHttpMetricsHeaders(NULL),
+	  mHttpMetricsHeaders(),
 	  mHttpMetricsPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
 	  mTotalCacheReadCount(0U),
 	  mTotalCacheWriteCount(0U),
@@ -2529,13 +2528,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 
 	LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
 	mHttpRequest = new LLCore::HttpRequest;
-	mHttpOptions = new LLCore::HttpOptions;
-	mHttpOptionsWithHeaders = new LLCore::HttpOptions;
+	mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+	mHttpOptionsWithHeaders = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
 	mHttpOptionsWithHeaders->setWantHeaders(true);
-	mHttpHeaders = new LLCore::HttpHeaders;
+    mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 	mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_TEXTURE);
-	mHttpMetricsHeaders = new LLCore::HttpHeaders;
+    mHttpMetricsHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 	mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	mHttpMetricsPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_REPORTING);
 	mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER;
@@ -2569,30 +2568,6 @@ LLTextureFetch::~LLTextureFetch()
 		delete req;
 	}
 
-	if (mHttpOptions)
-	{
-		mHttpOptions->release();
-		mHttpOptions = NULL;
-	}
-
-	if (mHttpOptionsWithHeaders)
-	{
-		mHttpOptionsWithHeaders->release();
-		mHttpOptionsWithHeaders = NULL;
-	}
-
-	if (mHttpHeaders)
-	{
-		mHttpHeaders->release();
-		mHttpHeaders = NULL;
-	}
-
-	if (mHttpMetricsHeaders)
-	{
-		mHttpMetricsHeaders->release();
-		mHttpMetricsHeaders = NULL;
-	}
-
 	mHttpWaitResource.clear();
 	
 	delete mHttpRequest;
@@ -3249,7 +3224,7 @@ void LLTextureFetch::sendRequestListToSimulators()
 	{
 		LLHost host = iter1->first;
 		// invalid host = use agent host
-		if (host == LLHost::invalid)
+		if (host.isInvalid())
 		{
 			host = gAgent.getRegionHost();
 		}
@@ -3329,7 +3304,7 @@ void LLTextureFetch::sendRequestListToSimulators()
 				 iter1 != mCancelQueue.end(); ++iter1)
 			{
 				LLHost host = iter1->first;
-				if (host == LLHost::invalid)
+				if (host.isInvalid())
 				{
 					host = gAgent.getRegionHost();
 				}
@@ -4044,7 +4019,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
 											report_priority,
 											mCapsURL,
 											sd,
-											NULL,
+											LLCore::HttpOptions::ptr_t(),
 											fetcher->getMetricsHeaders(),
 											handler);
 		LLTextureFetch::svMetricsDataBreak = false;
@@ -4163,7 +4138,7 @@ LLTextureFetchDebugger::LLTextureFetchDebugger(LLTextureFetch* fetcher, LLTextur
 	mFetcher(fetcher),
 	mTextureCache(cache),
 	mImageDecodeThread(imagedecodethread),
-	mHttpHeaders(NULL),
+	mHttpHeaders(),
 	mHttpPolicyClass(fetcher->getPolicyClass()),
 	mNbCurlCompleted(0),
 	mTempIndex(0),
@@ -4177,11 +4152,6 @@ LLTextureFetchDebugger::~LLTextureFetchDebugger()
 	mFetchingHistory.clear();
 	mStopDebug = TRUE;
 	tryToStopDebug();
-	if (mHttpHeaders)
-	{
-		mHttpHeaders->release();
-		mHttpHeaders = NULL;
-	}
 }
 
 void LLTextureFetchDebugger::init()
@@ -4226,7 +4196,7 @@ void LLTextureFetchDebugger::init()
 
 	if (! mHttpHeaders)
 	{
-		mHttpHeaders = new LLCore::HttpHeaders;
+        mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
 		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	}
 }
@@ -4626,7 +4596,7 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
 																				   texture_url,
 																				   0,
 																				   requestedSize,
-																				   NULL,
+																				   LLCore::HttpOptions::ptr_t(),
 																				   mHttpHeaders,
 																				   this);
 		if (LLCORE_HTTP_HANDLE_INVALID != handle)
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 27779a31e0ad93294302f07cced692754d8fdc2e..50233eee5edd0fa4931763d19a8149ec3a62ea34 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -37,7 +37,6 @@
 #include "lltextureinfo.h"
 #include "llapr.h"
 #include "llimageworker.h"
-#include "llcurl.h"
 #include "httprequest.h"
 #include "httpoptions.h"
 #include "httpheaders.h"
@@ -177,7 +176,7 @@ class LLTextureFetch : public LLWorkerThread
 	// to do that to hold a reference for any length of time.
 	//
 	// Threads:  T*
-	LLCore::HttpHeaders * getMetricsHeaders() const	{ return mHttpMetricsHeaders; }
+	LLCore::HttpHeaders::ptr_t getMetricsHeaders() const	{ return mHttpMetricsHeaders; }
 
 	// Threads:  T*
 	LLCore::HttpRequest::policy_t getMetricsPolicyClass() const { return mHttpMetricsPolicyClass; }
@@ -354,11 +353,11 @@ class LLTextureFetch : public LLWorkerThread
 	// to make our HTTP requests.  These replace the various
 	// LLCurl interfaces used in the past.
 	LLCore::HttpRequest *				mHttpRequest;					// Ttf
-	LLCore::HttpOptions *				mHttpOptions;					// Ttf
-	LLCore::HttpOptions *				mHttpOptionsWithHeaders;		// Ttf
-	LLCore::HttpHeaders *				mHttpHeaders;					// Ttf
+	LLCore::HttpOptions::ptr_t			mHttpOptions;					// Ttf
+	LLCore::HttpOptions::ptr_t			mHttpOptionsWithHeaders;		// Ttf
+	LLCore::HttpHeaders::ptr_t			mHttpHeaders;					// Ttf
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;				// T*
-	LLCore::HttpHeaders *				mHttpMetricsHeaders;			// Ttf
+	LLCore::HttpHeaders::ptr_t			mHttpMetricsHeaders;			// Ttf
 	LLCore::HttpRequest::policy_t		mHttpMetricsPolicyClass;		// T*
 	S32									mHttpHighWater;					// Ttf
 	S32									mHttpLowWater;					// Ttf
@@ -510,7 +509,7 @@ class LLTextureFetchDebugger : public LLCore::HttpHandler
 	LLTextureFetch* mFetcher;
 	LLTextureCache* mTextureCache;
 	LLImageDecodeThread* mImageDecodeThread;
-	LLCore::HttpHeaders* mHttpHeaders;
+	LLCore::HttpHeaders::ptr_t mHttpHeaders;
 	LLCore::HttpRequest::policy_t mHttpPolicyClass;
 	
 	S32 mNumFetchedTextures;
diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp
index ca42d710f8cd5eceb4bc5d26e39b3cbbc72fa192..8ded148e178dfb7271c6d1d9a648fbb0895133fb 100755
--- a/indra/newview/lltexturestats.cpp
+++ b/indra/newview/lltexturestats.cpp
@@ -30,8 +30,8 @@
 #include "llagent.h"
 #include "lltexturefetch.h" 
 #include "lltexturestats.h"
-#include "lltexturestatsuploader.h"
 #include "llviewerregion.h"
+#include "llcorehttputil.h"
 
 void send_texture_stats_to_sim(const LLSD &texture_stats)
 {
@@ -49,6 +49,16 @@ void send_texture_stats_to_sim(const LLSD &texture_stats)
 
 	std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
 	LL_INFOS() << "uploading texture stats data to simulator" << LL_ENDL;
-	LLTextureStatsUploader::uploadStatsToSimulator(texture_cap_url, texture_stats);
+
+    if (texture_cap_url != "")
+    {
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(texture_cap_url, texture_stats,
+            "Texture statistics posted to sim.", "Error posting texture statistics to sim");
+    }
+    else
+    {
+        LL_INFOS() << "Not sending texture stats: " << texture_stats
+            << " as there is no cap url." << LL_ENDL;
+    }
 }
 
diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/lltexturestatsuploader.cpp
deleted file mode 100755
index c4809bc8e78c06c9ebe9c33a3ed2c3c9c4f3e0e8..0000000000000000000000000000000000000000
--- a/indra/newview/lltexturestatsuploader.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/** 
- * @file lltexturerstats.cpp
- * @brief texture stats upload class
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "lltexturestatsuploader.h"
-
-#include "llhttpclient.h"
-
-
-// static
-void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
-{
-	if ( texture_cap_url != "" )
-	{
-		LLHTTPClient::post(texture_cap_url, texture_stats, NULL);
-	}
-	else
-	{
-		LL_INFOS() << "Not sending texture stats: " 
-				<< texture_stats 
-				<< " as there is no cap url." 
-				<< LL_ENDL;
-	}
-}
-
diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/lltexturestatsuploader.h
deleted file mode 100755
index ac268c2516baaf7d877e734e723421263083e1c5..0000000000000000000000000000000000000000
--- a/indra/newview/lltexturestatsuploader.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/** 
- * @file lltexturestatsuploader.h
- * @brief Class to send the texture stats to the simulatore
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTEXTURESTATSUPLOADER_H
-#define LL_LLTEXTURESTATSUPLOADER_H
-
-#include "llappviewer.h"
-
-// utility functions to capture data on texture download speeds and send to simulator periodically
-
-class LLTextureStatsUploader
-{
-public:
-	static void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
-};
-
-#endif // LL_LLTEXTURESTATSUPLOADER_H
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 81fbc471b39f370753d9bfc9d72fd8a00a97a257..8f482c5dca9f78580117bbf0b0e198a52e7c2d36 100755
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -821,21 +821,6 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
 
 	if (!handled)
 	{
-        // *TODO: Suppress the "outbox" case once "marketplace" is used everywhere for everyone
-		// Disallow drag and drop to 3D from the outbox
-		const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-		if (outbox_id.notNull())
-		{
-			for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
-			{
-				if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id))
-				{
-					*acceptance = ACCEPT_NO;
-					mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld");
-					return;
-				}
-			}
-		}
 		// Disallow drag and drop to 3D from the marketplace
         const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
 		if (marketplacelistings_id.notNull())
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index c0ba0a1f39d9911d84433850614616f7b461574b..76fba82ef67f33785e50bbe8462e85521c873755 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -35,31 +35,254 @@
 #include "llui.h"
 #include "llversioninfo.h"
 #include "llviewercontrol.h"
-
+#include "llcoros.h"
 #include "reader.h"
+#include "llcorehttputil.h"
+
+
+/**
+* Handler of an HTTP machine translation service.
+*
+* Derived classes know the service URL
+* and how to parse the translation result.
+*/
+class LLTranslationAPIHandler
+{
+public:
+    typedef std::pair<std::string, std::string> LanguagePair_t;
+
+    /**
+    * Get URL for translation of the given string.
+    *
+    * Sending HTTP GET request to the URL will initiate translation.
+    *
+    * @param[out] url        Place holder for the result.
+    * @param      from_lang  Source language. Leave empty for auto-detection.
+    * @param      to_lang    Target language.
+    * @param      text       Text to translate.
+    */
+    virtual std::string getTranslateURL(
+        const std::string &from_lang,
+        const std::string &to_lang,
+        const std::string &text) const = 0;
+
+    /**
+    * Get URL to verify the given API key.
+    *
+    * Sending request to the URL verifies the key.
+    * Positive HTTP response (code 200) means that the key is valid.
+    *
+    * @param[out] url  Place holder for the URL.
+    * @param[in]  key  Key to verify.
+    */
+    virtual std::string getKeyVerificationURL(
+        const std::string &key) const = 0;
+
+    /**
+    * Parse translation response.
+    *
+    * @param[in,out] status        HTTP status. May be modified while parsing.
+    * @param         body          Response text.
+    * @param[out]    translation   Translated text.
+    * @param[out]    detected_lang Detected source language. May be empty.
+    * @param[out]    err_msg       Error message (in case of error).
+    */
+    virtual bool parseResponse(
+        int& status,
+        const std::string& body,
+        std::string& translation,
+        std::string& detected_lang,
+        std::string& err_msg) const = 0;
+
+    /**
+    * @return if the handler is configured to function properly
+    */
+    virtual bool isConfigured() const = 0;
+
+    virtual void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) = 0;
+    virtual void translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
+
+
+    virtual ~LLTranslationAPIHandler() {}
+
+    void verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc);
+    void translateMessageCoro(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
+};
+
+void LLTranslationAPIHandler::translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
+{
+    LLCoros::instance().launch("Translation", boost::bind(&LLTranslationAPIHandler::translateMessageCoro,
+        this, fromTo, msg, success, failure));
+
+}
+
+
+void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+
+    std::string user_agent = llformat("%s %d.%d.%d (%d)",
+        LLVersionInfo::getChannel().c_str(),
+        LLVersionInfo::getMajor(),
+        LLVersionInfo::getMinor(),
+        LLVersionInfo::getPatch(),
+        LLVersionInfo::getBuild());
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+    httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
+
+    httpOpts->setFollowRedirects(true);
+
+    std::string url = this->getKeyVerificationURL(key);
+    if (url.empty())
+    {
+        LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
+        return;
+    }
 
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    bool bOk = true;
+    if (!status)
+        bOk = false;
+
+    if (!fnc.empty())
+        fnc(service, bOk);
+}
+
+void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::string msg,
+    LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+
+    std::string user_agent = llformat("%s %d.%d.%d (%d)",
+        LLVersionInfo::getChannel().c_str(),
+        LLVersionInfo::getMajor(),
+        LLVersionInfo::getMinor(),
+        LLVersionInfo::getPatch(),
+        LLVersionInfo::getBuild());
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+    httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
+
+    std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg);
+    if (url.empty())
+    {
+        LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
+        return;
+    }
+
+    LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    std::string translation, detected_lang, err_msg;
+
+    int parseResult = status.getType();
+    if (this->parseResponse(parseResult, result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asString(), 
+        translation, detected_lang, err_msg))
+    {
+        // Fix up the response
+        LLStringUtil::replaceString(translation, "&lt;", "<");
+        LLStringUtil::replaceString(translation, "&gt;", ">");
+        LLStringUtil::replaceString(translation, "&quot;", "\"");
+        LLStringUtil::replaceString(translation, "&#39;", "'");
+        LLStringUtil::replaceString(translation, "&amp;", "&");
+        LLStringUtil::replaceString(translation, "&apos;", "'");
+
+        if (!success.empty())
+            success(translation, detected_lang);
+    }
+    else
+    {
+        if (err_msg.empty())
+        {
+            err_msg = LLTrans::getString("TranslationResponseParseError");
+        }
+
+        LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
+        if (!failure.empty())
+            failure(status, err_msg);
+    }
+
+
+}
+
+//=========================================================================
+/// Google Translate v2 API handler.
+class LLGoogleTranslationHandler : public LLTranslationAPIHandler
+{
+    LOG_CLASS(LLGoogleTranslationHandler);
+
+public:
+    /*virtual*/ std::string getTranslateURL(
+        const std::string &from_lang,
+        const std::string &to_lang,
+        const std::string &text) const;
+    /*virtual*/ std::string getKeyVerificationURL(
+        const std::string &key) const;
+    /*virtual*/ bool parseResponse(
+        int& status,
+        const std::string& body,
+        std::string& translation,
+        std::string& detected_lang,
+        std::string& err_msg) const;
+    /*virtual*/ bool isConfigured() const;
+
+    /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
+
+private:
+    static void parseErrorResponse(
+        const Json::Value& root,
+        int& status,
+        std::string& err_msg);
+    static bool parseTranslation(
+        const Json::Value& root,
+        std::string& translation,
+        std::string& detected_lang);
+    static std::string getAPIKey();
+
+};
+
+//-------------------------------------------------------------------------
 // virtual
-void LLGoogleTranslationHandler::getTranslateURL(
-	std::string &url,
+std::string LLGoogleTranslationHandler::getTranslateURL(
 	const std::string &from_lang,
 	const std::string &to_lang,
 	const std::string &text) const
 {
-	url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+	std::string url = std::string("https://www.googleapis.com/language/translate/v2?key=")
 		+ getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
 	if (!from_lang.empty())
 	{
 		url += "&source=" + from_lang;
 	}
+    return url;
 }
 
 // virtual
-void LLGoogleTranslationHandler::getKeyVerificationURL(
-	std::string& url,
+std::string LLGoogleTranslationHandler::getKeyVerificationURL(
 	const std::string& key) const
 {
-	url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
+	std::string url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
 		+ key + "&target=en";
+    return url;
 }
 
 // virtual
@@ -154,28 +377,66 @@ std::string LLGoogleTranslationHandler::getAPIKey()
 	return gSavedSettings.getString("GoogleTranslateAPIKey");
 }
 
+/*virtual*/ 
+void LLGoogleTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
+{
+    LLCoros::instance().launch("Google /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
+        this, LLTranslate::SERVICE_GOOGLE, key, fnc));
+}
+
+
+//=========================================================================
+/// Microsoft Translator v2 API handler.
+class LLBingTranslationHandler : public LLTranslationAPIHandler
+{
+    LOG_CLASS(LLBingTranslationHandler);
+
+public:
+    /*virtual*/ std::string getTranslateURL(
+        const std::string &from_lang,
+        const std::string &to_lang,
+        const std::string &text) const;
+    /*virtual*/ std::string getKeyVerificationURL(
+        const std::string &key) const;
+    /*virtual*/ bool parseResponse(
+        int& status,
+        const std::string& body,
+        std::string& translation,
+        std::string& detected_lang,
+        std::string& err_msg) const;
+    /*virtual*/ bool isConfigured() const;
+
+    /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
+private:
+    static std::string getAPIKey();
+    static std::string getAPILanguageCode(const std::string& lang);
+
+};
+
+//-------------------------------------------------------------------------
 // virtual
-void LLBingTranslationHandler::getTranslateURL(
-	std::string &url,
+std::string LLBingTranslationHandler::getTranslateURL(
 	const std::string &from_lang,
 	const std::string &to_lang,
 	const std::string &text) const
 {
-	url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+	std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
 		+ getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang);
 	if (!from_lang.empty())
 	{
 		url += "&from=" + getAPILanguageCode(from_lang);
 	}
+    return url;
 }
 
+
 // virtual
-void LLBingTranslationHandler::getKeyVerificationURL(
-	std::string& url,
+std::string LLBingTranslationHandler::getKeyVerificationURL(
 	const std::string& key) const
 {
-	url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
+	std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
 		+ key;
+    return url;
 }
 
 // virtual
@@ -242,96 +503,31 @@ std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang
 	return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese
 }
 
-LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
-:	mFromLang(from_lang)
-,	mToLang(to_lang)
-,	mHandler(LLTranslate::getPreferredHandler())
+/*virtual*/
+void LLBingTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
 {
+    LLCoros::instance().launch("Bing /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, 
+        this, LLTranslate::SERVICE_BING, key, fnc));
 }
 
-// virtual
-void LLTranslate::TranslationReceiver::completedRaw(
-	const LLChannelDescriptors& channels,
-	const LLIOPipe::buffer_ptr_t& buffer)
+//=========================================================================
+/*static*/
+void LLTranslate::translateMessage(const std::string &from_lang, const std::string &to_lang,
+    const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure)
 {
-	LLBufferStream istr(channels, buffer.get());
-	std::stringstream strstrm;
-	strstrm << istr.rdbuf();
-
-	const std::string body = strstrm.str();
-	std::string translation, detected_lang, err_msg;
-	int status = getStatus();
-	LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL;
-	LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
-	if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
-	{
-		// Fix up the response
-		LLStringUtil::replaceString(translation, "&lt;", "<");
-		LLStringUtil::replaceString(translation, "&gt;",">");
-		LLStringUtil::replaceString(translation, "&quot;","\"");
-		LLStringUtil::replaceString(translation, "&#39;","'");
-		LLStringUtil::replaceString(translation, "&amp;","&");
-		LLStringUtil::replaceString(translation, "&apos;","'");
-
-		handleResponse(translation, detected_lang);
-	}
-	else
-	{
-		if (err_msg.empty())
-		{
-			err_msg = LLTrans::getString("TranslationResponseParseError");
-		}
+    LLTranslationAPIHandler& handler = getPreferredHandler();
 
-		LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
-		handleFailure(status, err_msg);
-	}
+    handler.translateMessage(LLTranslationAPIHandler::LanguagePair_t(from_lang, to_lang), mesg, success, failure);
 }
 
-LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service)
-:	mService(service)
+/*static*/
+void LLTranslate::verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc)
 {
-}
+    LLTranslationAPIHandler& handler = getHandler(service);
 
-LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
-{
-	return mService;
+    handler.verifyKey(key, fnc);
 }
 
-// virtual
-void LLTranslate::KeyVerificationReceiver::completedRaw(
-	const LLChannelDescriptors& channels,
-	const LLIOPipe::buffer_ptr_t& buffer)
-{
-	bool ok = (getStatus() == HTTP_OK);
-	setVerificationStatus(ok);
-}
-
-//static
-void LLTranslate::translateMessage(
-	TranslationReceiverPtr &receiver,
-	const std::string &from_lang,
-	const std::string &to_lang,
-	const std::string &mesg)
-{
-	std::string url;
-	receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
-
-	LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
-	sendRequest(url, receiver);
-}
-
-// static
-void LLTranslate::verifyKey(
-	KeyVerificationReceiverPtr& receiver,
-	const std::string& key)
-{
-	std::string url;
-	const LLTranslationAPIHandler& handler = getHandler(receiver->getService());
-	handler.getKeyVerificationURL(url, key);
-
-	LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL;
-	sendRequest(url, receiver);
-}
 
 //static
 std::string LLTranslate::getTranslateLanguage()
@@ -352,7 +548,7 @@ bool LLTranslate::isTranslationConfigured()
 }
 
 // static
-const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
+LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
 {
 	EService service = SERVICE_BING;
 
@@ -366,7 +562,7 @@ const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
 }
 
 // static
-const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
+LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
 {
 	static LLGoogleTranslationHandler google;
 	static LLBingTranslationHandler bing;
@@ -378,25 +574,3 @@ const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
 
 	return bing;
 }
-
-// static
-void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder)
-{
-	static const float REQUEST_TIMEOUT = 5;
-	static LLSD sHeader;
-
-	if (!sHeader.size())
-	{
-	    std::string user_agent = llformat("%s %d.%d.%d (%d)",
-			LLVersionInfo::getChannel().c_str(),
-			LLVersionInfo::getMajor(),
-			LLVersionInfo::getMinor(),
-			LLVersionInfo::getPatch(),
-			LLVersionInfo::getBuild());
-
-		sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
-		sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent);
-	}
-
-	LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
-}
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index 972274714a073607d8b498bbdaba01475ac51ac6..bf431cdfbb23ca2d983cdb1bc779f2ee4f6c9e9e 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -27,136 +27,15 @@
 #ifndef LL_LLTRANSLATE_H
 #define LL_LLTRANSLATE_H
 
-#include "llhttpclient.h"
 #include "llbufferstream.h"
+#include <boost/function.hpp>
 
 namespace Json
 {
     class Value;
 }
 
-/**
- * Handler of an HTTP machine translation service.
- *
- * Derived classes know the service URL
- * and how to parse the translation result.
- */
-class LLTranslationAPIHandler
-{
-public:
-	/**
-	 * Get URL for translation of the given string.
-	 *
-	 * Sending HTTP GET request to the URL will initiate translation.
-	 *
-	 * @param[out] url        Place holder for the result.
-	 * @param      from_lang  Source language. Leave empty for auto-detection.
-	 * @param      to_lang    Target language.
-	 * @param      text       Text to translate.
-	 */
-	virtual void getTranslateURL(
-		std::string &url,
-		const std::string &from_lang,
-		const std::string &to_lang,
-		const std::string &text) const = 0;
-
-	/**
-	 * Get URL to verify the given API key.
-	 *
-	 * Sending request to the URL verifies the key.
-	 * Positive HTTP response (code 200) means that the key is valid.
-	 *
-	 * @param[out] url  Place holder for the URL.
-	 * @param[in]  key  Key to verify.
-	 */
-	virtual void getKeyVerificationURL(
-		std::string &url,
-		const std::string &key) const = 0;
-
-	/**
-	 * Parse translation response.
-	 *
-	 * @param[in,out] status        HTTP status. May be modified while parsing.
-	 * @param         body          Response text.
-	 * @param[out]    translation   Translated text.
-	 * @param[out]    detected_lang Detected source language. May be empty.
-	 * @param[out]    err_msg       Error message (in case of error).
-	 */
-	virtual bool parseResponse(
-		int& status,
-		const std::string& body,
-		std::string& translation,
-		std::string& detected_lang,
-		std::string& err_msg) const = 0;
-
-	/**
-	 * @return if the handler is configured to function properly
-	 */
-	virtual bool isConfigured() const = 0;
-
-	virtual ~LLTranslationAPIHandler() {}
-};
-
-/// Google Translate v2 API handler.
-class LLGoogleTranslationHandler : public LLTranslationAPIHandler
-{
-	LOG_CLASS(LLGoogleTranslationHandler);
-
-public:
-	/*virtual*/ void getTranslateURL(
-		std::string &url,
-		const std::string &from_lang,
-		const std::string &to_lang,
-		const std::string &text) const;
-	/*virtual*/ void getKeyVerificationURL(
-		std::string &url,
-		const std::string &key) const;
-	/*virtual*/ bool parseResponse(
-		int& status,
-		const std::string& body,
-		std::string& translation,
-		std::string& detected_lang,
-		std::string& err_msg) const;
-	/*virtual*/ bool isConfigured() const;
-
-private:
-	static void parseErrorResponse(
-		const Json::Value& root,
-		int& status,
-		std::string& err_msg);
-	static bool parseTranslation(
-		const Json::Value& root,
-		std::string& translation,
-		std::string& detected_lang);
-	static std::string getAPIKey();
-};
-
-/// Microsoft Translator v2 API handler.
-class LLBingTranslationHandler : public LLTranslationAPIHandler
-{
-	LOG_CLASS(LLBingTranslationHandler);
-
-public:
-	/*virtual*/ void getTranslateURL(
-		std::string &url,
-		const std::string &from_lang,
-		const std::string &to_lang,
-		const std::string &text) const;
-	/*virtual*/ void getKeyVerificationURL(
-		std::string &url,
-		const std::string &key) const;
-	/*virtual*/ bool parseResponse(
-		int& status,
-		const std::string& body,
-		std::string& translation,
-		std::string& detected_lang,
-		std::string& err_msg) const;
-	/*virtual*/ bool isConfigured() const;
-private:
-	static std::string getAPIKey();
-	static std::string getAPILanguageCode(const std::string& lang);
-};
-
+class LLTranslationAPIHandler;
 /**
  * Entry point for machine translation services.
  *
@@ -180,84 +59,9 @@ public :
 		SERVICE_GOOGLE,
 	} EService;
 
-	/**
-	 * Subclasses are supposed to handle translation results (e.g. show them in chat)
-	 */
-	class TranslationReceiver: public LLHTTPClient::Responder
-	{
-	public:
-
-		/**
-		 * Using mHandler, parse incoming response.
-		 *
-		 * Calls either handleResponse() or handleFailure()
-		 * depending on the HTTP status code and parsing success.
-		 *
-		 * @see handleResponse()
-		 * @see handleFailure()
-		 * @see mHandler
-		 */
-		/*virtual*/ void completedRaw(
-			const LLChannelDescriptors& channels,
-			const LLIOPipe::buffer_ptr_t& buffer);
-
-	protected:
-		friend class LLTranslate;
-
-		/// Remember source and target languages for subclasses to be able to filter inappropriate results.
-		TranslationReceiver(const std::string& from_lang, const std::string& to_lang);
-
-		/// Override point to handle successful translation.
-		virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0;
-
-		/// Override point to handle unsuccessful translation.
-		virtual void handleFailure(int status, const std::string& err_msg) = 0;
-
-		std::string mFromLang;
-		std::string mToLang;
-		const LLTranslationAPIHandler& mHandler;
-	};
-
-	/**
-	 * Subclasses are supposed to handle API key verification result.
-	 */
-	class KeyVerificationReceiver: public LLHTTPClient::Responder
-	{
-	public:
-		EService getService() const;
-
-	protected:
-		/**
-		 * Save the translation service the key belongs to.
-		 *
-		 * Subclasses need to know it.
-		 *
-		 * @see getService()
-		 */
-		KeyVerificationReceiver(EService service);
-
-		/**
-		 * Parse verification response.
-		 *
-		 * Calls setVerificationStatus() with the verification status,
-		 * which is true if HTTP status code is 200.
-		 *
-		 * @see setVerificationStatus()
-		 */
-		/*virtual*/ void completedRaw(
-			const LLChannelDescriptors& channels,
-			const LLIOPipe::buffer_ptr_t& buffer);
-
-		/**
-		 * Override point for subclasses to handle key verification status.
-		 */
-		virtual void setVerificationStatus(bool ok) = 0;
-
-		EService mService;
-	};
-
-	typedef LLPointer<TranslationReceiver> TranslationReceiverPtr;
-	typedef LLPointer<KeyVerificationReceiver> KeyVerificationReceiverPtr;
+    typedef boost::function<void(EService, bool)> KeyVerificationResult_fn;
+    typedef boost::function<void(std::string , std::string )> TranslationSuccess_fn;
+    typedef boost::function<void(int, std::string)> TranslationFailure_fn;
 
 	/**
 	 * Translate given text.
@@ -267,15 +71,15 @@ public :
 	 * @param to_lang    Target language.
 	 * @param mesg       Text to translate.
 	 */
-	static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
+    static void translateMessage(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure);
 
-	/**
+    /**
 	 * Verify given API key of a translation service.
 	 *
 	 * @param receiver  Object to pass verification result to.
 	 * @param key       Key to verify.
 	 */
-	static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key);
+    static void verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc);
 
 	/**
 	 * @return translation target language
@@ -288,9 +92,8 @@ public :
 	static bool isTranslationConfigured();
 
 private:
-	static const LLTranslationAPIHandler& getPreferredHandler();
-	static const LLTranslationAPIHandler& getHandler(EService service);
-	static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder);
+	static LLTranslationAPIHandler& getPreferredHandler();
+	static LLTranslationAPIHandler& getHandler(EService service);
 };
 
 #endif
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index e983bc883f1452e92dc8f4f95537287745a6b533..9b7c13b57d2e884e5cf806bf034d46f302dbe1c9 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -32,7 +32,6 @@
 #include "llagent.h"
 #include "llcallingcard.h"			// for LLAvatarTracker
 #include "llcommandhandler.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llurlaction.h"
 #include "llimagepng.h"
@@ -43,6 +42,7 @@
 
 #include "llfloaterwebcontent.h"
 #include "llfloaterreg.h"
+#include "llcorehttputil.h"
 
 boost::scoped_ptr<LLEventPump> LLTwitterConnect::sStateWatcher(new LLEventStream("TwitterConnectState"));
 boost::scoped_ptr<LLEventPump> LLTwitterConnect::sInfoWatcher(new LLEventStream("TwitterConnectInfo"));
@@ -67,228 +67,305 @@ void toast_user_for_twitter_success()
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLTwitterConnectResponder : public LLHTTPClient::Responder
+void LLTwitterConnect::twitterConnectCoro(std::string requestToken, std::string oauthVerifier)
 {
-	LOG_CLASS(LLTwitterConnectResponder);
-public:
-	
-    LLTwitterConnectResponder()
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD body;
+    if (!requestToken.empty())
+        body["request_token"] = requestToken;
+    if (!oauthVerifier.empty())
+        body["oauth_verifier"] = oauthVerifier;
+
+    LLSD result = httpAdapter->putAndSuspend(httpRequest, getTwitterConnectURL("/connection"), body, httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
     {
-        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+        if ( status == LLCore::HttpStatus(HTTP_FOUND) )
+        {
+            std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+            if (location.empty())
+            {
+                LL_WARNS("FlickrConnect") << "Missing Location header " << LL_ENDL;
+            }
+            else
+            {
+                openTwitterWeb(location);
+            }
+        }
+        else
+        {
+            LL_WARNS("TwitterConnect") << "Connection failed " << status.toString() << LL_ENDL;
+            setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+            log_twitter_connect_error("Connect", status.getStatus(), status.toString(),
+                result.get("error_code"), result.get("error_description"));
+        }
     }
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLTwitterConnect::instance().openTwitterWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
-			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
-			const LLSD& content = getContent();
-			log_twitter_connect_error("Connect", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    else
+    {
+        LL_DEBUGS("TwitterConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLTwitterShareResponder : public LLHTTPClient::Responder
+bool LLTwitterConnect::testShareStatus(LLSD &result)
 {
-	LOG_CLASS(LLTwitterShareResponder);
-public:
-    
-	LLTwitterShareResponder()
-	{
-		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTING);
-	}
-	
-	/* virtual */ void httpSuccess()
-	{
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status)
+        return true;
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("TwitterConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openTwitterWeb(location);
+        }
+    }
+    if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+    {
+        LL_DEBUGS("TwitterConnect") << "Not connected. " << LL_ENDL;
+        connectToTwitter();
+    }
+    else
+    {
+        LL_WARNS("TwitterConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
+        log_twitter_connect_error("Share", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    return false;
+}
+
+void LLTwitterConnect::twitterShareCoro(std::string route, LLSD share)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getTwitterConnectURL(route, true), share, httpOpts);
+
+    if (testShareStatus(result))
+    {
         toast_user_for_twitter_success();
-		LL_DEBUGS("TwitterConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
-        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLTwitterConnect::instance().openTwitterWeb(location);
-			}
-		}
-		else if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LLTwitterConnect::instance().connectToTwitter();
-		}
-		else
-		{
-			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
-            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
-			const LLSD& content = getContent();
-			log_twitter_connect_error("Share", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+        LL_DEBUGS("TwitterConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_POSTED);
+    }
+}
+
+void LLTwitterConnect::twitterShareImageCoro(LLPointer<LLImageFormatted> image, std::string status)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    std::string imageFormat;
+    if (dynamic_cast<LLImagePNG*>(image.get()))
+    {
+        imageFormat = "png";
+    }
+    else if (dynamic_cast<LLImageJPEG*>(image.get()))
+    {
+        imageFormat = "jpg";
+    }
+    else
+    {
+        LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
+        return;
+    }
+
+    // All this code is mostly copied from LLWebProfile::post()
+    const std::string boundary = "----------------------------0123abcdefab";
+
+    std::string contentType = "multipart/form-data; boundary=" + boundary;
+    httpHeaders->append("Content-Type", contentType.c_str());
+
+    LLCore::BufferArray::ptr_t raw = LLCore::BufferArray::ptr_t(new LLCore::BufferArray()); // 
+    LLCore::BufferArrayStream body(raw.get());
+
+    // *NOTE: The order seems to matter.
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"status\"\r\n\r\n"
+        << status << "\r\n";
+
+    body << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
+        << "Content-Type: image/" << imageFormat << "\r\n\r\n";
+
+    // Insert the image data.
+    // *FIX: Treating this as a string will probably screw it up ...
+    U8* image_data = image->getData();
+    for (S32 i = 0; i < image->getDataSize(); ++i)
+    {
+        body << image_data[i];
+    }
+
+    body << "\r\n--" << boundary << "--\r\n";
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, getTwitterConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
+
+    if (testShareStatus(result))
+    {
+        toast_user_for_twitter_success();
+        LL_DEBUGS("TwitterConnect") << "Post successful. " << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_POSTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLTwitterDisconnectResponder : public LLHTTPClient::Responder
+void LLTwitterConnect::twitterDisconnectCoro()
 {
-	LOG_CLASS(LLTwitterDisconnectResponder);
-public:
- 
-	LLTwitterDisconnectResponder()
-	{
-		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
-	}
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	void setUserDisconnected()
-	{
-		// Clear data
-		LLTwitterConnect::instance().clearInfo();
+    httpOpts->setFollowRedirects(false);
 
-		//Notify state change
-		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
-	}
+    LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getTwitterConnectURL("/connection"), httpOpts);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("TwitterConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
-		setUserDisconnected();
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		//User not found so already disconnected
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("TwitterConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
-			setUserDisconnected();
-		}
-		else
-		{
-			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
-			LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
-			const LLSD& content = getContent();
-			log_twitter_connect_error("Disconnect", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status && (status != LLCore::HttpStatus(HTTP_NOT_FOUND)))
+    {
+        LL_WARNS("TwitterConnect") << "Disconnect failed!" << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
+
+        log_twitter_connect_error("Disconnect", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_DEBUGS("TwitterConnect") << "Disconnect successful. " << LL_ENDL;
+        clearInfo();
+        setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLTwitterConnectedResponder : public LLHTTPClient::Responder
+void LLTwitterConnect::twitterConnectedCoro(bool autoConnect)
 {
-	LOG_CLASS(LLTwitterConnectedResponder);
-public:
-    
-	LLTwitterConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+    httpOpts->setFollowRedirects(false);
+    setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getTwitterConnectURL("/connection", true), httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
+        {
+            LL_DEBUGS("TwitterConnect") << "Not connected. " << LL_ENDL;
+            if (autoConnect)
+            {
+                connectToTwitter();
+            }
+            else
+            {
+                setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
+            }
+        }
+        else
+        {
+            LL_WARNS("TwitterConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
+
+            setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
+            log_twitter_connect_error("Connected", status.getStatus(), status.toString(),
+                result.get("error_code"), result.get("error_description"));
+        }
+    }
+    else
     {
-		LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+        LL_DEBUGS("TwitterConnect") << "Connect successful. " << LL_ENDL;
+        setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
     }
-    
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
-        LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		// show the facebook login page if not connected yet
-		if ( HTTP_NOT_FOUND == getStatus() )
-		{
-			LL_DEBUGS("TwitterConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
-			if (mAutoConnect)
-			{
-                LLTwitterConnect::instance().connectToTwitter();
-			}
-			else
-			{
-                LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
-			}
-		}
-		else
-		{
-			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
-            LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
-			const LLSD& content = getContent();
-			log_twitter_connect_error("Connected", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-    
-private:
-	bool mAutoConnect;
-};
+
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
-class LLTwitterInfoResponder : public LLHTTPClient::Responder
+void LLTwitterConnect::twitterInfoCoro()
 {
-	LOG_CLASS(LLTwitterInfoResponder);
-public:
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
-	/* virtual */ void httpSuccess()
-	{
-		LL_INFOS("TwitterConnect") << "Twitter: Info received" << LL_ENDL;
-		LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. " << dumpResponse() << LL_ENDL;
-        LLTwitterConnect::instance().storeInfo(getContent());
-	}
-    
-	/* virtual */ void httpFailure()
-	{
-		if ( HTTP_FOUND == getStatus() )
-		{
-			const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (location.empty())
-			{
-				LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
-                << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			}
-			else
-			{
-                LLTwitterConnect::instance().openTwitterWeb(location);
-			}
-		}
-		else
-		{
-			LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
-			const LLSD& content = getContent();
-			log_twitter_connect_error("Info", getStatus(), getReason(),
-									   content.get("error_code"), content.get("error_description"));
-		}
-	}
-};
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, getTwitterConnectURL("/info", true), httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status == LLCore::HttpStatus(HTTP_FOUND))
+    {
+        std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
+        if (location.empty())
+        {
+            LL_WARNS("TwitterConnect") << "Missing Location header " << LL_ENDL;
+        }
+        else
+        {
+            openTwitterWeb(location);
+        }
+    }
+    else if (!status)
+    {
+        LL_WARNS("TwitterConnect") << "Twitter Info failed: " << status.toString() << LL_ENDL;
+        log_twitter_connect_error("Info", status.getStatus(), status.toString(),
+            result.get("error_code"), result.get("error_description"));
+    }
+    else
+    {
+        LL_INFOS("TwitterConnect") << "Twitter: Info received" << LL_ENDL;
+        result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+        storeInfo(result);
+    }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //
@@ -341,36 +418,32 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
 
 void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier)
 {
-	LLSD body;
-	if (!request_token.empty())
-		body["request_token"] = request_token;
-	if (!oauth_verifier.empty())
-		body["oauth_verifier"] = oauth_verifier;
-    
-	LLHTTPClient::put(getTwitterConnectURL("/connection"), body, new LLTwitterConnectResponder());
+    setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+
+    LLCoros::instance().launch("LLTwitterConnect::twitterConnectCoro",
+        boost::bind(&LLTwitterConnect::twitterConnectCoro, this, request_token, oauth_verifier));
 }
 
 void LLTwitterConnect::disconnectFromTwitter()
 {
-	LLHTTPClient::del(getTwitterConnectURL("/connection"), new LLTwitterDisconnectResponder());
+    setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
+
+    LLCoros::instance().launch("LLTwitterConnect::twitterDisconnectCoro",
+        boost::bind(&LLTwitterConnect::twitterDisconnectCoro, this));
 }
 
 void LLTwitterConnect::checkConnectionToTwitter(bool auto_connect)
 {
-	const bool follow_redirects = false;
-	const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-	LLHTTPClient::get(getTwitterConnectURL("/connection", true), new LLTwitterConnectedResponder(auto_connect),
-						LLSD(), timeout, follow_redirects);
+    LLCoros::instance().launch("LLTwitterConnect::twitterConnectedCoro",
+        boost::bind(&LLTwitterConnect::twitterConnectedCoro, this, auto_connect));
 }
 
 void LLTwitterConnect::loadTwitterInfo()
 {
 	if(mRefreshInfo)
 	{
-		const bool follow_redirects = false;
-		const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
-		LLHTTPClient::get(getTwitterConnectURL("/info", true), new LLTwitterInfoResponder(),
-			LLSD(), timeout, follow_redirects);
+        LLCoros::instance().launch("LLTwitterConnect::twitterInfoCoro",
+            boost::bind(&LLTwitterConnect::twitterInfoCoro, this));
 	}
 }
 
@@ -379,62 +452,19 @@ void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::stri
 	LLSD body;
 	body["image"] = image_url;
 	body["status"] = status;
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getTwitterConnectURL("/share/photo", true), body, new LLTwitterShareResponder());
+
+    setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+
+    LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
+        boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/photo", body));
 }
 
 void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status)
 {
-	std::string imageFormat;
-	if (dynamic_cast<LLImagePNG*>(image.get()))
-	{
-		imageFormat = "png";
-	}
-	else if (dynamic_cast<LLImageJPEG*>(image.get()))
-	{
-		imageFormat = "jpg";
-	}
-	else
-	{
-		LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
-		return;
-	}
-	
-	// All this code is mostly copied from LLWebProfile::post()
-	const std::string boundary = "----------------------------0123abcdefab";
-
-	LLSD headers;
-	headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
+    setConnectionState(LLTwitterConnect::TWITTER_POSTING);
 
-	std::ostringstream body;
-
-	// *NOTE: The order seems to matter.
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"status\"\r\n\r\n"
-			<< status << "\r\n";
-
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
-			<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
-
-	// Insert the image data.
-	// *FIX: Treating this as a string will probably screw it up ...
-	U8* image_data = image->getData();
-	for (S32 i = 0; i < image->getDataSize(); ++i)
-	{
-		body << image_data[i];
-	}
-
-	body <<	"\r\n--" << boundary << "--\r\n";
-
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = body.str().size();
-	U8 *data = new U8[size];
-	memcpy(data, body.str().data(), size);
-	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::postRaw(getTwitterConnectURL("/share/photo", true), data, size, new LLTwitterShareResponder(), headers);
+    LLCoros::instance().launch("LLTwitterConnect::twitterShareImageCoro",
+        boost::bind(&LLTwitterConnect::twitterShareImageCoro, this, image, status));
 }
 
 void LLTwitterConnect::updateStatus(const std::string& status)
@@ -442,8 +472,10 @@ void LLTwitterConnect::updateStatus(const std::string& status)
 	LLSD body;
 	body["status"] = status;
 	
-    // Note: we can use that route for different publish action. We should be able to use the same responder.
-	LLHTTPClient::post(getTwitterConnectURL("/share/status", true), body, new LLTwitterShareResponder());
+    setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+
+    LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
+        boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/status", body));
 }
 
 void LLTwitterConnect::storeInfo(const LLSD& info)
diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h
index c1df13f18cf558ea934ebe35983c770a6f84bc2e..be481a17c10b9f4e27f97dea1cd8c79145f2150f 100644
--- a/indra/newview/lltwitterconnect.h
+++ b/indra/newview/lltwitterconnect.h
@@ -30,6 +30,8 @@
 
 #include "llsingleton.h"
 #include "llimage.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
 
 class LLEventPump;
 
@@ -94,6 +96,14 @@ class LLTwitterConnect : public LLSingleton<LLTwitterConnect>
 	static boost::scoped_ptr<LLEventPump> sStateWatcher;
 	static boost::scoped_ptr<LLEventPump> sInfoWatcher;
 	static boost::scoped_ptr<LLEventPump> sContentWatcher;
+
+    bool testShareStatus(LLSD &result);
+    void twitterConnectCoro(std::string requestToken, std::string oauthVerifier);
+    void twitterDisconnectCoro();
+    void twitterConnectedCoro(bool autoConnect);
+    void twitterInfoCoro();
+    void twitterShareCoro(std::string route, LLSD share);
+    void twitterShareImageCoro(LLPointer<LLImageFormatted> image, std::string status);
 };
 
 #endif // LL_LLTWITTERCONNECT_H
diff --git a/indra/newview/lluploadfloaterobservers.cpp b/indra/newview/lluploadfloaterobservers.cpp
deleted file mode 100755
index 69b9b1f9f1aba978cb185f1a40da55ff86c8a1fd..0000000000000000000000000000000000000000
--- a/indra/newview/lluploadfloaterobservers.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @file lluploadfloaterobservers.cpp
- * @brief LLUploadModelPermissionsResponder definition
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "lluploadfloaterobservers.h"
-
-LLUploadModelPermissionsResponder::LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer)
-:mObserverHandle(observer)
-{
-}
-
-void LLUploadModelPermissionsResponder::httpFailure()
-{
-	LL_WARNS() << dumpResponse() << LL_ENDL;
-
-	LLUploadPermissionsObserver* observer = mObserverHandle.get();
-
-	if (observer)
-	{
-		observer->setPermissonsErrorStatus(getStatus(), getReason());
-	}
-}
-
-void LLUploadModelPermissionsResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap())
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	LLUploadPermissionsObserver* observer = mObserverHandle.get();
-
-	if (observer)
-	{
-		observer->onPermissionsReceived(content);
-	}
-}
-
diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h
index 4ff4a827a5ee5f9a409e5f4052909a9d064add6d..15c3dad38e6ba2e843308f40f358a282f2001463 100755
--- a/indra/newview/lluploadfloaterobservers.h
+++ b/indra/newview/lluploadfloaterobservers.h
@@ -28,7 +28,6 @@
 #define LL_LLUPLOADFLOATEROBSERVERS_H
 
 #include "llfloater.h"
-#include "llhttpclient.h"
 #include "llhandle.h"
 
 class LLUploadPermissionsObserver
@@ -79,18 +78,4 @@ class LLWholeModelUploadObserver
 	LLRootHandle<LLWholeModelUploadObserver> mWholeModelUploadObserverHandle;
 };
 
-
-class LLUploadModelPermissionsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLUploadModelPermissionsResponder);
-public:
-	LLUploadModelPermissionsResponder(const LLHandle<LLUploadPermissionsObserver>& observer);
-
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
-
-	LLHandle<LLUploadPermissionsObserver> mObserverHandle;
-};
-
 #endif /* LL_LLUPLOADFLOATEROBSERVERS_H */
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea3d81c2f6260dfb86fe2ec65e9f77b6549806cd
--- /dev/null
+++ b/indra/newview/llviewerassetupload.cpp
@@ -0,0 +1,839 @@
+/**
+* @file llviewerassetupload.cpp
+* @author optional
+* @brief brief description of the file
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "linden_common.h"
+#include "llviewertexturelist.h"
+#include "llimage.h"
+#include "lltrans.h"
+#include "lluuid.h"
+#include "llvorbisencode.h"
+#include "lluploaddialog.h"
+#include "llpreviewscript.h"
+#include "llnotificationsutil.h"
+#include "lleconomy.h"
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llstatusbar.h"
+#include "llinventorypanel.h"
+#include "llsdutil.h"
+#include "llviewerassetupload.h"
+#include "llappviewer.h"
+#include "llviewerstats.h"
+#include "llvfile.h"
+#include "llgesturemgr.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewgesture.h"
+#include "llcoproceduremanager.h"
+
+void dialog_refresh_all();
+
+LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
+        LLAssetType::EType assetType, std::string name, std::string description,
+        S32 compressionInfo, LLFolderType::EType destinationType,
+        LLInventoryType::EType inventoryType, U32 nextOWnerPerms,
+        U32 groupPerms, U32 everyonePerms, S32 expectedCost) :
+    mTransactionId(transactId),
+    mAssetType(assetType),
+    mName(name),
+    mDescription(description),
+    mCompressionInfo(compressionInfo),
+    mDestinationFolderType(destinationType),
+    mInventoryType(inventoryType),
+    mNextOwnerPerms(nextOWnerPerms),
+    mGroupPerms(groupPerms),
+    mEveryonePerms(everyonePerms),
+    mExpectedUploadCost(expectedCost),
+    mFolderId(LLUUID::null),
+    mItemId(LLUUID::null),
+    mAssetId(LLAssetID::null)
+{ }
+
+
+LLResourceUploadInfo::LLResourceUploadInfo(std::string name, 
+        std::string description, S32 compressionInfo, 
+        LLFolderType::EType destinationType, LLInventoryType::EType inventoryType, 
+        U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost):
+    mName(name),
+    mDescription(description),
+    mCompressionInfo(compressionInfo),
+    mDestinationFolderType(destinationType),
+    mInventoryType(inventoryType),
+    mNextOwnerPerms(nextOWnerPerms),
+    mGroupPerms(groupPerms),
+    mEveryonePerms(everyonePerms),
+    mExpectedUploadCost(expectedCost),
+    mTransactionId(),
+    mAssetType(LLAssetType::AT_NONE),
+    mFolderId(LLUUID::null),
+    mItemId(LLUUID::null),
+    mAssetId(LLAssetID::null)
+{ 
+    mTransactionId.generate();
+}
+
+LLResourceUploadInfo::LLResourceUploadInfo(LLAssetID assetId, LLAssetType::EType assetType, std::string name) :
+    mAssetId(assetId),
+    mAssetType(assetType),
+    mName(name),
+    mDescription(),
+    mCompressionInfo(0),
+    mDestinationFolderType(LLFolderType::FT_NONE),
+    mInventoryType(LLInventoryType::IT_NONE),
+    mNextOwnerPerms(0),
+    mGroupPerms(0),
+    mEveryonePerms(0),
+    mExpectedUploadCost(0),
+    mTransactionId(),
+    mFolderId(LLUUID::null),
+    mItemId(LLUUID::null)
+{
+}
+
+LLSD LLResourceUploadInfo::prepareUpload()
+{
+    if (mAssetId.isNull())
+        generateNewAssetId();
+
+    incrementUploadStats();
+    assignDefaults();
+
+    return LLSD().with("success", LLSD::Boolean(true));
+}
+
+std::string LLResourceUploadInfo::getAssetTypeString() const
+{
+    return LLAssetType::lookup(mAssetType);
+}
+
+std::string LLResourceUploadInfo::getInventoryTypeString() const
+{
+    return LLInventoryType::lookup(mInventoryType);
+}
+
+LLSD LLResourceUploadInfo::generatePostBody()
+{
+    LLSD body;
+
+    body["folder_id"] = mFolderId;
+    body["asset_type"] = getAssetTypeString();
+    body["inventory_type"] = getInventoryTypeString();
+    body["name"] = mName;
+    body["description"] = mDescription;
+    body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms);
+    body["group_mask"] = LLSD::Integer(mGroupPerms);
+    body["everyone_mask"] = LLSD::Integer(mEveryonePerms);
+
+    return body;
+
+}
+
+void LLResourceUploadInfo::logPreparedUpload()
+{
+    LL_INFOS() << "*** Uploading: " << std::endl <<
+        "Type: " << LLAssetType::lookup(mAssetType) << std::endl <<
+        "UUID: " << mAssetId.asString() << std::endl <<
+        "Name: " << mName << std::endl <<
+        "Desc: " << mDescription << std::endl <<
+        "Expected Upload Cost: " << mExpectedUploadCost << std::endl <<
+        "Folder: " << mFolderId << std::endl <<
+        "Asset Type: " << LLAssetType::lookup(mAssetType) << LL_ENDL;
+}
+
+S32 LLResourceUploadInfo::getEconomyUploadCost()
+{
+    // Update L$ and ownership credit information
+    // since it probably changed on the server
+    if (getAssetType() == LLAssetType::AT_TEXTURE ||
+        getAssetType() == LLAssetType::AT_SOUND ||
+        getAssetType() == LLAssetType::AT_ANIMATION ||
+        getAssetType() == LLAssetType::AT_MESH)
+    {
+        return LLGlobalEconomy::Singleton::instance().getPriceUpload();
+    }
+
+    return 0;
+}
+
+
+LLUUID LLResourceUploadInfo::finishUpload(LLSD &result)
+{
+    if (getFolderId().isNull())
+    {
+        return LLUUID::null;
+    }
+
+    U32 permsEveryone = PERM_NONE;
+    U32 permsGroup = PERM_NONE;
+    U32 permsNextOwner = PERM_ALL;
+
+    if (result.has("new_next_owner_mask"))
+    {
+        // The server provided creation perms so use them.
+        // Do not assume we got the perms we asked for in
+        // since the server may not have granted them all.
+        permsEveryone = result["new_everyone_mask"].asInteger();
+        permsGroup = result["new_group_mask"].asInteger();
+        permsNextOwner = result["new_next_owner_mask"].asInteger();
+    }
+    else
+    {
+        // The server doesn't provide creation perms
+        // so use old assumption-based perms.
+        if (getAssetTypeString() != "snapshot")
+        {
+            permsNextOwner = PERM_MOVE | PERM_TRANSFER;
+        }
+    }
+
+    LLPermissions new_perms;
+    new_perms.init(
+        gAgent.getID(),
+        gAgent.getID(),
+        LLUUID::null,
+        LLUUID::null);
+
+    new_perms.initMasks(
+        PERM_ALL,
+        PERM_ALL,
+        permsEveryone,
+        permsGroup,
+        permsNextOwner);
+
+    U32 flagsInventoryItem = 0;
+    if (result.has("inventory_flags"))
+    {
+        flagsInventoryItem = static_cast<U32>(result["inventory_flags"].asInteger());
+        if (flagsInventoryItem != 0)
+        {
+            LL_INFOS() << "inventory_item_flags " << flagsInventoryItem << LL_ENDL;
+        }
+    }
+    S32 creationDate = time_corrected();
+
+    LLUUID serverInventoryItem = result["new_inventory_item"].asUUID();
+    LLUUID serverAssetId = result["new_asset"].asUUID();
+
+    LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
+        serverInventoryItem,
+        getFolderId(),
+        new_perms,
+        serverAssetId,
+        getAssetType(),
+        getInventoryType(),
+        getName(),
+        getDescription(),
+        LLSaleInfo::DEFAULT,
+        flagsInventoryItem,
+        creationDate);
+
+    gInventory.updateItem(item);
+    gInventory.notifyObservers();
+
+    return serverInventoryItem;
+}
+
+
+LLAssetID LLResourceUploadInfo::generateNewAssetId()
+{
+    if (gDisconnected)
+    {
+        LLAssetID rv;
+
+        rv.setNull();
+        return rv;
+    }
+    mAssetId = mTransactionId.makeAssetID(gAgent.getSecureSessionID());
+
+    return mAssetId;
+}
+
+void LLResourceUploadInfo::incrementUploadStats() const
+{
+    if (LLAssetType::AT_SOUND == mAssetType)
+    {
+        add(LLStatViewer::UPLOAD_SOUND, 1);
+    }
+    else if (LLAssetType::AT_TEXTURE == mAssetType)
+    {
+        add(LLStatViewer::UPLOAD_TEXTURE, 1);
+    }
+    else if (LLAssetType::AT_ANIMATION == mAssetType)
+    {
+        add(LLStatViewer::ANIMATION_UPLOADS, 1);
+    }
+}
+
+void LLResourceUploadInfo::assignDefaults()
+{
+    if (LLInventoryType::IT_NONE == mInventoryType)
+    {
+        mInventoryType = LLInventoryType::defaultForAssetType(mAssetType);
+    }
+    LLStringUtil::stripNonprintable(mName);
+    LLStringUtil::stripNonprintable(mDescription);
+
+    if (mName.empty())
+    {
+        mName = "(No Name)";
+    }
+    if (mDescription.empty())
+    {
+        mDescription = "(No Description)";
+    }
+
+    mFolderId = gInventory.findCategoryUUIDForType(
+        (mDestinationFolderType == LLFolderType::FT_NONE) ?
+        (LLFolderType::EType)mAssetType : mDestinationFolderType);
+
+}
+
+std::string LLResourceUploadInfo::getDisplayName() const
+{
+    return (mName.empty()) ? mAssetId.asString() : mName;
+};
+
+//=========================================================================
+LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(
+    std::string fileName,
+    std::string name,
+    std::string description,
+    S32 compressionInfo,
+    LLFolderType::EType destinationType,
+    LLInventoryType::EType inventoryType,
+    U32 nextOWnerPerms,
+    U32 groupPerms,
+    U32 everyonePerms,
+    S32 expectedCost) :
+    LLResourceUploadInfo(name, description, compressionInfo,
+    destinationType, inventoryType,
+    nextOWnerPerms, groupPerms, everyonePerms, expectedCost),
+    mFileName(fileName)
+{
+}
+
+LLSD LLNewFileResourceUploadInfo::prepareUpload()
+{
+    if (getAssetId().isNull())
+        generateNewAssetId();
+
+    LLSD result = exportTempFile();
+    if (result.has("error"))
+        return result;
+
+    return LLResourceUploadInfo::prepareUpload();
+}
+
+LLSD LLNewFileResourceUploadInfo::exportTempFile()
+{
+    std::string filename = gDirUtilp->getTempFilename();
+
+    std::string exten = gDirUtilp->getExtension(getFileName());
+    U32 codec = LLImageBase::getCodecFromExtension(exten);
+
+    LLAssetType::EType assetType = LLAssetType::AT_NONE;
+    std::string errorMessage;
+    std::string errorLabel;
+
+    bool error = false;
+
+    if (exten.empty())
+    {
+        std::string shortName = gDirUtilp->getBaseFileName(filename);
+
+        // No extension
+        errorMessage = llformat(
+            "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
+            shortName.c_str());
+        errorLabel = "NoFileExtension";
+        error = true;
+    }
+    else if (codec != IMG_CODEC_INVALID)
+    {
+        // It's an image file, the upload procedure is the same for all
+        assetType = LLAssetType::AT_TEXTURE;
+        if (!LLViewerTextureList::createUploadFile(getFileName(), filename, codec))
+        {
+            errorMessage = llformat("Problem with file %s:\n\n%s\n",
+                getFileName().c_str(), LLImage::getLastError().c_str());
+            errorLabel = "ProblemWithFile";
+            error = true;
+        }
+    }
+    else if (exten == "wav")
+    {
+        assetType = LLAssetType::AT_SOUND;  // tag it as audio
+        S32 encodeResult = 0;
+
+        LL_INFOS() << "Attempting to encode wav as an ogg file" << LL_ENDL;
+
+        encodeResult = encode_vorbis_file(getFileName(), filename);
+
+        if (LLVORBISENC_NOERR != encodeResult)
+        {
+            switch (encodeResult)
+            {
+            case LLVORBISENC_DEST_OPEN_ERR:
+                errorMessage = llformat("Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
+                errorLabel = "CannotOpenTemporarySoundFile";
+                break;
+
+            default:
+                errorMessage = llformat("Unknown vorbis encode failure on: %s\n", getFileName().c_str());
+                errorLabel = "UnknownVorbisEncodeFailure";
+                break;
+            }
+            error = true;
+        }
+    }
+    else if (exten == "bvh")
+    {
+        errorMessage = llformat("We do not currently support bulk upload of animation files\n");
+        errorLabel = "DoNotSupportBulkAnimationUpload";
+        error = true;
+    }
+    else if (exten == "anim")
+    {
+        assetType = LLAssetType::AT_ANIMATION;
+        filename = getFileName();
+    }
+    else
+    {
+        // Unknown extension
+        errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
+        errorLabel = "ErrorMessage";
+        error = TRUE;;
+    }
+
+    if (error)
+    {
+        LLSD errorResult(LLSD::emptyMap());
+
+        errorResult["error"] = LLSD::Binary(true);
+        errorResult["message"] = errorMessage;
+        errorResult["label"] = errorLabel;
+        return errorResult;
+    }
+
+    setAssetType(assetType);
+
+    // copy this file into the vfs for upload
+    S32 file_size;
+    LLAPRFile infile;
+    infile.open(filename, LL_APR_RB, NULL, &file_size);
+    if (infile.getFileHandle())
+    {
+        LLVFile file(gVFS, getAssetId(), assetType, LLVFile::WRITE);
+
+        file.setMaxSize(file_size);
+
+        const S32 buf_size = 65536;
+        U8 copy_buf[buf_size];
+        while ((file_size = infile.read(copy_buf, buf_size)))
+        {
+            file.write(copy_buf, file_size);
+        }
+    }
+    else
+    {
+        errorMessage = llformat("Unable to access output file: %s", filename.c_str());
+        LLSD errorResult(LLSD::emptyMap());
+
+        errorResult["error"] = LLSD::Binary(true);
+        errorResult["message"] = errorMessage;
+        return errorResult;
+    }
+
+    return LLSD();
+
+}
+
+//=========================================================================
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish) :
+    LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+        0, 0, 0, 0),
+    mTaskUpload(false),
+    mTaskId(LLUUID::null),
+    mContents(buffer),
+    mInvnFinishFn(finish),
+    mTaskFinishFn(NULL),
+    mStoredToVFS(false)
+{
+    setItemId(itemId);
+    setAssetType(assetType);
+}
+
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish) :
+    LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+        0, 0, 0, 0),
+    mTaskUpload(false),
+    mTaskId(LLUUID::null),
+    mContents(),
+    mInvnFinishFn(finish),
+    mTaskFinishFn(NULL),
+    mStoredToVFS(false)
+{
+    setItemId(itemId);
+
+    EImageCodec codec = static_cast<EImageCodec>(image->getCodec());
+
+    switch (codec)
+    {
+    case IMG_CODEC_JPEG:
+        setAssetType(LLAssetType::AT_IMAGE_JPEG);
+        LL_INFOS() << "Upload Asset type set to JPEG." << LL_ENDL;
+        break;
+    case IMG_CODEC_TGA:
+        setAssetType(LLAssetType::AT_IMAGE_TGA);
+        LL_INFOS() << "Upload Asset type set to TGA." << LL_ENDL;
+        break;
+    default:
+        LL_WARNS() << "Unknown codec to asset type transition. Codec=" << (int)codec << "." << LL_ENDL;
+        break;
+    }
+
+    size_t imageSize = image->getDataSize();
+    mContents.reserve(imageSize);
+    mContents.assign((char *)image->getData(), imageSize);
+}
+
+LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish) :
+    LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+        0, 0, 0, 0),
+    mTaskUpload(true),
+    mTaskId(taskId),
+    mContents(buffer),
+    mInvnFinishFn(NULL),
+    mTaskFinishFn(finish),
+    mStoredToVFS(false)
+{
+    setItemId(itemId);
+    setAssetType(assetType);
+}
+
+LLSD LLBufferedAssetUploadInfo::prepareUpload()
+{
+    if (getAssetId().isNull())
+        generateNewAssetId();
+
+    LLVFile file(gVFS, getAssetId(), getAssetType(), LLVFile::APPEND);
+
+    S32 size = mContents.length() + 1;
+    file.setMaxSize(size);
+    file.write((U8*)mContents.c_str(), size);
+
+    mStoredToVFS = true;
+
+    return LLSD().with("success", LLSD::Boolean(true));
+}
+
+LLSD LLBufferedAssetUploadInfo::generatePostBody()
+{
+    LLSD body;
+
+    if (!getTaskId().isNull())
+    {
+        body["task_id"] = getTaskId();
+    }
+    body["item_id"] = getItemId();
+
+    return body;
+}
+
+LLUUID LLBufferedAssetUploadInfo::finishUpload(LLSD &result)
+{
+    LLUUID newAssetId = result["new_asset"].asUUID();
+    LLUUID itemId = getItemId();
+
+    if (mStoredToVFS)
+    {
+        LLAssetType::EType assetType(getAssetType());
+        gVFS->renameFile(getAssetId(), assetType, newAssetId, assetType);
+    }
+
+    if (mTaskUpload)
+    {
+        LLUUID taskId = getTaskId();
+
+        dialog_refresh_all();
+
+        if (mTaskFinishFn)
+        {
+            mTaskFinishFn(itemId, taskId, newAssetId, result);
+        }
+    }
+    else
+    {
+        LLUUID newItemId(LLUUID::null);
+
+        if (itemId.notNull())
+        {
+            LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(itemId);
+            if (!item)
+            {
+                LL_WARNS() << "Inventory item for " << getDisplayName() << " is no longer in agent inventory." << LL_ENDL;
+                return newAssetId;
+            }
+
+            // Update viewer inventory item
+            LLPointer<LLViewerInventoryItem> newItem = new LLViewerInventoryItem(item);
+            newItem->setAssetUUID(newAssetId);
+
+            gInventory.updateItem(newItem);
+
+            newItemId = newItem->getUUID();
+            LL_INFOS() << "Inventory item " << item->getName() << " saved into " << newAssetId.asString() << LL_ENDL;
+        }
+
+        if (mInvnFinishFn)
+        {
+            mInvnFinishFn(itemId, newAssetId, newItemId, result);
+        }
+        gInventory.notifyObservers();
+    }
+
+    return newAssetId;
+}
+
+//=========================================================================
+
+LLScriptAssetUpload::LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish):
+    LLBufferedAssetUploadInfo(itemId, LLAssetType::AT_LSL_TEXT, buffer, finish),
+    mExerienceId(),
+    mTargetType(LSL2),
+    mIsRunning(false)
+{
+}
+
+LLScriptAssetUpload::LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType,
+        bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish):
+    LLBufferedAssetUploadInfo(taskId, itemId, LLAssetType::AT_LSL_TEXT, buffer, finish),
+    mExerienceId(exerienceId),
+    mTargetType(targetType),
+    mIsRunning(isRunning)
+{
+}
+
+LLSD LLScriptAssetUpload::generatePostBody()
+{
+    LLSD body;
+
+    if (getTaskId().isNull())
+    {
+        body["item_id"] = getItemId();
+        body["target"] = "lsl2";
+    }
+    else
+    {
+        body["task_id"] = getTaskId();
+        body["item_id"] = getItemId();
+        body["is_script_running"] = getIsRunning();
+        body["target"] = (getTargetType() == MONO) ? "mono" : "lsl2";
+        body["experience"] = getExerienceId();
+    }
+
+    return body;
+}
+
+//=========================================================================
+/*static*/
+LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const LLResourceUploadInfo::ptr_t &uploadInfo)
+{
+    std::string procName("LLViewerAssetUpload::AssetInventoryUploadCoproc(");
+    
+    LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload", 
+        procName + LLAssetType::lookup(uploadInfo->getAssetType()) + ")",
+        boost::bind(&LLViewerAssetUpload::AssetInventoryUploadCoproc, _1, _2, url, uploadInfo));
+
+    return queueId;
+}
+
+//=========================================================================
+/*static*/
+void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, 
+    const LLUUID &id, std::string url, LLResourceUploadInfo::ptr_t uploadInfo)
+{
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = uploadInfo->prepareUpload();
+    uploadInfo->logPreparedUpload();
+
+    if (result.has("error"))
+    {
+        HandleUploadError(LLCore::HttpStatus(499), result, uploadInfo);
+        return;
+    }
+
+    llcoro::suspend();
+
+    if (uploadInfo->showUploadDialog())
+    {
+        std::string uploadMessage = "Uploading...\n\n";
+        uploadMessage.append(uploadInfo->getDisplayName());
+        LLUploadDialog::modalUploadDialog(uploadMessage);
+    }
+
+    LLSD body = uploadInfo->generatePostBody();
+
+    result = httpAdapter->postAndSuspend(httpRequest, url, body);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if ((!status) || (result.has("error")))
+    {
+        HandleUploadError(status, result, uploadInfo);
+        if (uploadInfo->showUploadDialog())
+            LLUploadDialog::modalUploadFinished();
+        return;
+    }
+
+    std::string uploader = result["uploader"].asString();
+
+    bool success = false;
+    if (!uploader.empty() && uploadInfo->getAssetId().notNull())
+    {
+        result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType());
+        httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+        status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+        if (!status)
+        {
+            HandleUploadError(status, result, uploadInfo);
+            if (uploadInfo->showUploadDialog())
+                LLUploadDialog::modalUploadFinished();
+            return;
+        }
+
+        S32 uploadPrice = uploadInfo->getEconomyUploadCost();
+
+        if (uploadPrice > 0)
+        {
+            // this upload costed us L$, update our balance
+            // and display something saying that it cost L$
+            LLStatusBar::sendMoneyBalanceRequest();
+
+            LLSD args;
+            args["AMOUNT"] = llformat("%d", uploadPrice);
+            LLNotificationsUtil::add("UploadPayment", args);
+        }
+    }
+    else
+    {
+        LL_WARNS() << "No upload url provided.  Nothing uploaded, responding with previous result." << LL_ENDL;
+    }
+    LLUUID serverInventoryItem = uploadInfo->finishUpload(result);
+
+    if (uploadInfo->showInventoryPanel())
+    {
+        if (serverInventoryItem.notNull())
+        {
+            success = true;
+
+            // Show the preview panel for textures and sounds to let
+            // user know that the image (or snapshot) arrived intact.
+            LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel();
+            if (panel)
+            {
+                LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+                panel->setSelection(serverInventoryItem, TAKE_FOCUS_NO);
+
+                // restore keyboard focus
+                gFocusMgr.setKeyboardFocus(focus);
+            }
+        }
+        else
+        {
+            LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL;
+        }
+    }
+
+    // remove the "Uploading..." message
+    if (uploadInfo->showUploadDialog())
+        LLUploadDialog::modalUploadFinished();
+
+    // Let the Snapshot floater know we have finished uploading a snapshot to inventory.
+    LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot");
+    if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot)
+    {
+        floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory")));
+    }
+}
+
+//=========================================================================
+/*static*/
+void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &result, LLResourceUploadInfo::ptr_t &uploadInfo)
+{
+    std::string reason;
+    std::string label("CannotUploadReason");
+
+    LL_WARNS() << ll_pretty_print_sd(result) << LL_ENDL;
+
+    if (result.has("label"))
+    {
+        label = result["label"].asString();
+    }
+
+    if (result.has("message"))
+    {
+        reason = result["message"].asString();
+    }
+    else
+    {
+        if (status.getType() == 499)
+        {
+            reason = "The server is experiencing unexpected difficulties.";
+        }
+        else
+        {
+            reason = "Error in upload request.  Please visit "
+                "http://secondlife.com/support for help fixing this problem.";
+        }
+    }
+
+    LLSD args;
+    args["FILE"] = uploadInfo->getDisplayName();
+    args["REASON"] = reason;
+
+    LLNotificationsUtil::add(label, args);
+
+    // unfreeze script preview
+    if (uploadInfo->getAssetType() == LLAssetType::AT_LSL_TEXT)
+    {
+        LLPreviewLSL* preview = LLFloaterReg::findTypedInstance<LLPreviewLSL>("preview_script", 
+            uploadInfo->getItemId());
+        if (preview)
+        {
+            LLSD errors;
+            errors.append(LLTrans::getString("UploadFailed") + reason);
+            preview->callbackLSLCompileFailed(errors);
+        }
+    }
+
+}
+
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
new file mode 100644
index 0000000000000000000000000000000000000000..43e23a0d42ff36315dafd90e986ac0b2b9ee4832
--- /dev/null
+++ b/indra/newview/llviewerassetupload.h
@@ -0,0 +1,236 @@
+/**
+* @file llviewerassetupload.h
+* @author optional
+* @brief brief description of the file
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_VIEWER_ASSET_UPLOAD_H
+#define LL_VIEWER_ASSET_UPLOAD_H
+
+#include "llfoldertype.h"
+#include "llassettype.h"
+#include "llinventorytype.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llcorehttputil.h"
+#include "llimage.h"
+
+//=========================================================================
+class LLResourceUploadInfo
+{
+public:
+    typedef boost::shared_ptr<LLResourceUploadInfo> ptr_t;
+
+    LLResourceUploadInfo(
+        LLTransactionID transactId,
+        LLAssetType::EType assetType,
+        std::string name,
+        std::string description,
+        S32 compressionInfo,
+        LLFolderType::EType destinationType,
+        LLInventoryType::EType inventoryType,
+        U32 nextOWnerPerms,
+        U32 groupPerms,
+        U32 everyonePerms,
+        S32 expectedCost);
+
+    virtual ~LLResourceUploadInfo()
+    { }
+
+    virtual LLSD        prepareUpload();
+    virtual LLSD        generatePostBody();
+    virtual void        logPreparedUpload();
+    virtual S32         getEconomyUploadCost();
+    virtual LLUUID      finishUpload(LLSD &result);
+
+    LLTransactionID     getTransactionId() const { return mTransactionId; }
+    LLAssetType::EType  getAssetType() const { return mAssetType; }
+    std::string         getAssetTypeString() const;
+    std::string         getName() const { return mName; };
+    std::string         getDescription() const { return mDescription; };
+    S32                 getCompressionInfo() const { return mCompressionInfo; };
+    LLFolderType::EType getDestinationFolderType() const { return mDestinationFolderType; };
+    LLInventoryType::EType  getInventoryType() const { return mInventoryType; };
+    std::string         getInventoryTypeString() const;
+    U32                 getNextOwnerPerms() const { return mNextOwnerPerms; };
+    U32                 getGroupPerms() const { return mGroupPerms; };
+    U32                 getEveryonePerms() const { return mEveryonePerms; };
+    S32                 getExpectedUploadCost() const { return mExpectedUploadCost; };
+
+    virtual bool        showUploadDialog() const { return true; }
+    virtual bool        showInventoryPanel() const { return true; }
+
+    virtual std::string getDisplayName() const;
+
+    LLUUID              getFolderId() const { return mFolderId; }
+    LLUUID              getItemId() const { return mItemId; }
+    LLAssetID           getAssetId() const { return mAssetId; }
+
+protected:
+    LLResourceUploadInfo(
+        std::string name,
+        std::string description,
+        S32 compressionInfo,
+        LLFolderType::EType destinationType,
+        LLInventoryType::EType inventoryType,
+        U32 nextOWnerPerms,
+        U32 groupPerms,
+        U32 everyonePerms,
+        S32 expectedCost);
+
+    LLResourceUploadInfo(
+        LLAssetID assetId,
+        LLAssetType::EType assetType,
+        std::string name );
+
+    void                setTransactionId(LLTransactionID tid) { mTransactionId = tid; }
+    void                setAssetType(LLAssetType::EType assetType) { mAssetType = assetType; }
+    void                setItemId(LLUUID itemId) { mItemId = itemId; }
+
+    LLAssetID           generateNewAssetId();
+    void                incrementUploadStats() const;
+    virtual void        assignDefaults();
+
+    void                setAssetId(LLUUID assetId) { mAssetId = assetId; }
+
+private:
+    LLTransactionID     mTransactionId;
+    LLAssetType::EType  mAssetType;
+    std::string         mName;
+    std::string         mDescription;
+    S32                 mCompressionInfo;
+    LLFolderType::EType mDestinationFolderType;
+    LLInventoryType::EType mInventoryType;
+    U32                 mNextOwnerPerms;
+    U32                 mGroupPerms;
+    U32                 mEveryonePerms;
+    S32                 mExpectedUploadCost;
+
+    LLUUID              mFolderId;
+    LLUUID              mItemId;
+    LLAssetID           mAssetId;
+};
+
+//-------------------------------------------------------------------------
+class LLNewFileResourceUploadInfo : public LLResourceUploadInfo
+{
+public:
+    LLNewFileResourceUploadInfo(
+        std::string fileName,
+        std::string name,
+        std::string description,
+        S32 compressionInfo,
+        LLFolderType::EType destinationType,
+        LLInventoryType::EType inventoryType,
+        U32 nextOWnerPerms,
+        U32 groupPerms,
+        U32 everyonePerms,
+        S32 expectedCost);
+
+    virtual LLSD        prepareUpload();
+
+    std::string         getFileName() const { return mFileName; };
+
+protected:
+
+    virtual LLSD        exportTempFile();
+
+private:
+    std::string         mFileName;
+
+};
+
+//-------------------------------------------------------------------------
+class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
+{
+public:
+    typedef boost::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
+    typedef boost::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
+
+    LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish);
+    LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
+    LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemId, LLAssetType::EType assetType, std::string buffer, taskUploadFinish_f finish);
+
+    virtual LLSD        prepareUpload();
+    virtual LLSD        generatePostBody();
+    virtual LLUUID      finishUpload(LLSD &result);
+
+    LLUUID              getTaskId() const { return mTaskId; }
+    const std::string & getContents() const { return mContents; }
+
+    virtual bool        showUploadDialog() const { return false; }
+    virtual bool        showInventoryPanel() const { return false; }
+
+protected:
+
+
+private:
+    bool                mTaskUpload;
+    LLUUID              mTaskId;
+    std::string         mContents;
+    invnUploadFinish_f  mInvnFinishFn;
+    taskUploadFinish_f  mTaskFinishFn;
+    bool                mStoredToVFS;
+};
+
+//-------------------------------------------------------------------------
+class LLScriptAssetUpload : public LLBufferedAssetUploadInfo
+{
+public:
+    enum TargetType_t
+    {
+        LSL2,
+        MONO
+    };
+
+    LLScriptAssetUpload(LLUUID itemId, std::string buffer, invnUploadFinish_f finish);
+    LLScriptAssetUpload(LLUUID taskId, LLUUID itemId, TargetType_t targetType, 
+            bool isRunning, LLUUID exerienceId, std::string buffer, taskUploadFinish_f finish);
+
+    virtual LLSD        generatePostBody();
+
+    LLUUID              getExerienceId() const { return mExerienceId; }
+    TargetType_t        getTargetType() const { return mTargetType; }
+    bool                getIsRunning() const { return mIsRunning; }
+
+private:
+    LLUUID              mExerienceId;
+    TargetType_t        mTargetType;
+    bool                mIsRunning;
+
+};
+
+//=========================================================================
+class LLViewerAssetUpload
+{
+public:
+    static LLUUID EnqueueInventoryUpload(const std::string &url, const LLResourceUploadInfo::ptr_t &uploadInfo);
+
+    static void AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, const LLUUID &id, std::string url, LLResourceUploadInfo::ptr_t uploadInfo);
+
+private:
+    static void HandleUploadError(LLCore::HttpStatus status, LLSD &result, LLResourceUploadInfo::ptr_t &uploadInfo);
+};
+
+#endif // !VIEWER_ASSET_UPLOAD_H
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
deleted file mode 100755
index e390e8776db446a2c67d0ca5c1cb20500642c8e4..0000000000000000000000000000000000000000
--- a/indra/newview/llviewerdisplayname.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/** 
- * @file llviewerdisplayname.cpp
- * @brief Wrapper for display name functionality
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llviewerdisplayname.h"
-
-// viewer includes
-#include "llagent.h"
-#include "llviewerregion.h"
-#include "llvoavatar.h"
-
-// library includes
-#include "llavatarnamecache.h"
-#include "llhttpclient.h"
-#include "llhttpnode.h"
-#include "llnotificationsutil.h"
-#include "llui.h"					// getLanguage()
-
-namespace LLViewerDisplayName
-{
-	// Fired when viewer receives server response to display name change
-	set_name_signal_t sSetDisplayNameSignal;
-
-	// Fired when there is a change in the agent's name
-	name_changed_signal_t sNameChangedSignal;
-
-	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb) 
-	{ 
-		sNameChangedSignal.connect(cb); 
-	}
-
-	void doNothing() { }
-}
-
-class LLSetDisplayNameResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLSetDisplayNameResponder);
-private:
-	// only care about errors
-	/*virtual*/ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-		LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
-		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
-	}
-};
-
-void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)
-{
-	// TODO: simple validation here
-
-	LLViewerRegion* region = gAgent.getRegion();
-	llassert(region);
-	std::string cap_url = region->getCapability("SetDisplayName");
-	if (cap_url.empty())
-	{
-		// this server does not support display names, report error
-		slot(false, "unsupported", LLSD());
-		return;
-	}
-
-	// People API can return localized error messages.  Indicate our
-	// language preference via header.
-	LLSD headers;
-	headers[HTTP_OUT_HEADER_ACCEPT_LANGUAGE] = LLUI::getLanguage();
-
-	// People API requires both the old and new value to change a variable.
-	// Our display name will be in cache before the viewer's UI is available
-	// to request a change, so we can use direct lookup without callback.
-	LLAvatarName av_name;
-	if (!LLAvatarNameCache::get( gAgent.getID(), &av_name))
-	{
-		slot(false, "name unavailable", LLSD());
-		return;
-	}
-
-	// People API expects array of [ "old value", "new value" ]
-	LLSD change_array = LLSD::emptyArray();
-	change_array.append(av_name.getDisplayName());
-	change_array.append(display_name);
-	
-	LL_INFOS() << "Set name POST to " << cap_url << LL_ENDL;
-
-	// Record our caller for when the server sends back a reply
-	sSetDisplayNameSignal.connect(slot);
-	
-	// POST the requested change.  The sim will not send a response back to
-	// this request directly, rather it will send a separate message after it
-	// communicates with the back-end.
-	LLSD body;
-	body["display_name"] = change_array;
-	LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers);
-}
-
-class LLSetDisplayNameReply : public LLHTTPNode
-{
-	LOG_CLASS(LLSetDisplayNameReply);
-public:
-	/*virtual*/ void post(
-		LLHTTPNode::ResponsePtr response,
-		const LLSD& context,
-		const LLSD& input) const
-	{
-		LLSD body = input["body"];
-
-		S32 status = body["status"].asInteger();
-		bool success = (status == HTTP_OK);
-		std::string reason = body["reason"].asString();
-		LLSD content = body["content"];
-
-		LL_INFOS() << "status " << status << " reason " << reason << LL_ENDL;
-
-		// If viewer's concept of display name is out-of-date, the set request
-		// will fail with 409 Conflict.  If that happens, fetch up-to-date
-		// name information.
-		if (status == HTTP_CONFLICT)
-		{
-			LLUUID agent_id = gAgent.getID();
-			// Flush stale data
-			LLAvatarNameCache::erase( agent_id );
-			// Queue request for new data: nothing to do on callback though...
-			// Note: no need to disconnect the callback as it never gets out of scope
-			LLAvatarNameCache::get(agent_id, boost::bind(&LLViewerDisplayName::doNothing));
-			// Kill name tag, as it is wrong
-			LLVOAvatar::invalidateNameTag( agent_id );
-		}
-
-		// inform caller of result
-		LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content);
-		LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
-	}
-};
-
-
-class LLDisplayNameUpdate : public LLHTTPNode
-{
-	/*virtual*/ void post(
-		LLHTTPNode::ResponsePtr response,
-		const LLSD& context,
-		const LLSD& input) const
-	{
-		LLSD body = input["body"];
-		LLUUID agent_id = body["agent_id"];
-		std::string old_display_name = body["old_display_name"];
-		// By convention this record is called "agent" in the People API
-		LLSD name_data = body["agent"];
-
-		// Inject the new name data into cache
-		LLAvatarName av_name;
-		av_name.fromLLSD( name_data );
-
-		LL_INFOS() << "name-update now " << LLDate::now()
-			<< " next_update " << LLDate(av_name.mNextUpdate)
-			<< LL_ENDL;
-
-		// Name expiration time may be provided in headers, or we may use a
-		// default value
-		// *TODO: get actual headers out of ResponsePtr
-		//LLSD headers = response->mHeaders;
-		LLSD headers;
-		av_name.mExpires = 
-			LLAvatarNameCache::nameExpirationFromHeaders(headers);
-
-		LLAvatarNameCache::insert(agent_id, av_name);
-
-		// force name tag to update
-		LLVOAvatar::invalidateNameTag(agent_id);
-
-		LLSD args;
-		args["OLD_NAME"] = old_display_name;
-		args["SLID"] = av_name.getUserName();
-		args["NEW_NAME"] = av_name.getDisplayName();
-		LLNotificationsUtil::add("DisplayNameUpdate", args);
-		if (agent_id == gAgent.getID())
-		{
-			LLViewerDisplayName::sNameChangedSignal();
-		}
-	}
-};
-
-LLHTTPRegistration<LLSetDisplayNameReply>
-    gHTTPRegistrationMessageSetDisplayNameReply(
-		"/message/SetDisplayNameReply");
-
-LLHTTPRegistration<LLDisplayNameUpdate>
-    gHTTPRegistrationMessageDisplayNameUpdate(
-		"/message/DisplayNameUpdate");
diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h
deleted file mode 100755
index 16d59ae43b2e04bd79cb3d70c4dd015997ac27a6..0000000000000000000000000000000000000000
--- a/indra/newview/llviewerdisplayname.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/** 
- * @file llviewerdisplayname.h
- * @brief Wrapper for display name functionality
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LLVIEWERDISPLAYNAME_H
-#define LLVIEWERDISPLAYNAME_H
-
-#include <boost/signals2.hpp>
-
-class LLSD;
-class LLUUID;
-
-namespace LLViewerDisplayName
-{
-	typedef boost::signals2::signal<
-		void (bool success, const std::string& reason, const LLSD& content)>
-			set_name_signal_t;
-	typedef set_name_signal_t::slot_type set_name_slot_t;
-	
-	typedef boost::signals2::signal<void (void)> name_changed_signal_t;
-	typedef name_changed_signal_t::slot_type name_changed_slot_t;
-
-	// Sends an update to the server to change a display name
-	// and call back when done.  May not succeed due to service
-	// unavailable or name not available.
-	void set(const std::string& display_name, const set_name_slot_t& slot); 
-	
-	void addNameChangedCallback(const name_changed_signal_t::slot_type& cb);
-}
-
-#endif // LLVIEWERDISPLAYNAME_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 117865240810f1b9c57b587d9fb9da122dee79cc..7e76db20c5e02a8db6ef5ad9889c0edd76b4db34 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -56,7 +56,6 @@
 #include "llfloaterconversationpreview.h"
 #include "llfloaterdeleteenvpreset.h"
 #include "llfloaterdestinations.h"
-#include "llfloaterdisplayname.h"
 #include "llfloatereditdaycycle.h"
 #include "llfloatereditsky.h"
 #include "llfloatereditwater.h"
@@ -92,7 +91,6 @@
 #include "llfloaternotificationsconsole.h"
 #include "llfloaterobjectweights.h"
 #include "llfloateropenobject.h"
-#include "llfloateroutbox.h"
 #include "llfloaterpathfindingcharacters.h"
 #include "llfloaterpathfindingconsole.h"
 #include "llfloaterpathfindinglinksets.h"
@@ -247,7 +245,6 @@ void LLViewerFloaterReg::registerFloaters()
 	LLInspectRemoteObjectUtil::registerFloater();
 	LLFloaterVoiceVolumeUtil::registerFloater();
 	LLNotificationsUI::registerFloater();
-	LLFloaterDisplayNameUtil::registerFloater();
 	
 	LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
 	LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>);
@@ -272,7 +269,6 @@ void LLViewerFloaterReg::registerFloaters()
 
 	LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
 	LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
-	LLFloaterReg::add("outbox", "floater_merchant_outbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutbox>);
 	LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
 	LLFloaterPayUtil::registerFloater();
 
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 158cacbc817be7b45a6c7d2d04bac86e709bdf1c..b8ff2cc9b4fee36e2bff7a9d220b6c76a62ff606 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -137,7 +137,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 	
 	bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
 	addEntry(LLFolderType::FT_INBOX, 				new ViewerFolderEntry("Received Items",			"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
-	addEntry(LLFolderType::FT_OUTBOX, 				new ViewerFolderEntry("Merchant Outbox",		"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
+	addEntry(LLFolderType::FT_OUTBOX, 				new ViewerFolderEntry("Merchant Outbox",		"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
 
 	addEntry(LLFolderType::FT_BASIC_ROOT, 			new ViewerFolderEntry("Basic Root",				"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
 
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 24096e32225739670ad7ddcb5c8daa9d127c568a..573791aca397858854125f7273b17298f63fd8f2 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -79,6 +79,16 @@ static const char * const LOG_INV("Inventory");
 static const char * const LOG_LOCAL("InventoryLocalize");
 static const char * const LOG_NOTECARD("copy_inventory_from_notecard");
 
+#if 1
+// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model.
+// temp code in transition
+void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
+{
+    if (cb.notNull())
+        cb->fire(id);
+}
+#endif
+
 ///----------------------------------------------------------------------------
 /// Helper class to store special inventory item names and their localized values.
 ///----------------------------------------------------------------------------
@@ -1280,16 +1290,14 @@ void link_inventory_array(const LLUUID& category,
 #endif
 	}
 
-	bool ais_ran = false;
-	if (AISCommand::isAPIAvailable())
+    if (AISAPI::isAvailable())
 	{
 		LLSD new_inventory = LLSD::emptyMap();
 		new_inventory["links"] = links;
-		LLPointer<AISCommand> cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb);
-		ais_ran = cmd_ptr->run_command();
+        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+        AISAPI::CreateInventory(category, new_inventory, cr);
 	}
-
-	if (!ais_ran)
+    else
 	{
 		LLMessageSystem* msg = gMessageSystem;
 		for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter )
@@ -1346,8 +1354,7 @@ void update_inventory_item(
 	LLPointer<LLInventoryCallback> cb)
 {
 	const LLUUID& item_id = update_item->getUUID();
-	bool ais_ran = false;
-	if (AISCommand::isAPIAvailable())
+    if (AISAPI::isAvailable())
 	{
 		LLSD updates = update_item->asLLSD();
 		// Replace asset_id and/or shadow_id with transaction_id (hash_id)
@@ -1361,10 +1368,10 @@ void update_inventory_item(
 			updates.erase("shadow_id");
 			updates["hash_id"] = update_item->getTransactionID();
 		}
-		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
-		ais_ran = cmd_ptr->run_command();
+        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+        AISAPI::UpdateItem(item_id, updates, cr);
 	}
-	if (!ais_ran)
+    else
 	{
 		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
 		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
@@ -1400,13 +1407,12 @@ void update_inventory_item(
 	const LLSD& updates,
 	LLPointer<LLInventoryCallback> cb)
 {
-	bool ais_ran = false;
-	if (AISCommand::isAPIAvailable())
+    if (AISAPI::isAvailable())
 	{
-		LLPointer<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
-		ais_ran = cmd_ptr->run_command();
+        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+        AISAPI::UpdateItem(item_id, updates, cr);
 	}
-	if (!ais_ran)
+    else
 	{
 		LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
 		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
@@ -1456,11 +1462,11 @@ void update_inventory_category(
 		LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
 		new_cat->fromLLSD(updates);
 		// FIXME - restore this once the back-end work has been done.
-		if (AISCommand::isAPIAvailable())
+        if (AISAPI::isAvailable())
 		{
 			LLSD new_llsd = new_cat->asLLSD();
-			LLPointer<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
-			cmd_ptr->run_command();
+            AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+            AISAPI::UpdateCategory(cat_id, new_llsd, cr);
 		}
 		else // no cap
 		{
@@ -1522,10 +1528,10 @@ void remove_inventory_item(
 	{
 		const LLUUID item_id(obj->getUUID());
 		LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL;
-		if (AISCommand::isAPIAvailable())
+        if (AISAPI::isAvailable())
 		{
-			LLPointer<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
-			cmd_ptr->run_command();
+            AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+            AISAPI::RemoveItem(item_id, cr);
 
 			if (immediate_delete)
 			{
@@ -1598,10 +1604,10 @@ void remove_inventory_category(
 			LLNotificationsUtil::add("CannotRemoveProtectedCategories");
 			return;
 		}
-		if (AISCommand::isAPIAvailable())
+        if (AISAPI::isAvailable())
 		{
-			LLPointer<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
-			cmd_ptr->run_command();
+            AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+            AISAPI::RemoveCategory(cat_id, cr);
 		}
 		else // no cap
 		{
@@ -1701,10 +1707,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
 		}
 		else
 		{
-			if (AISCommand::isAPIAvailable())
+            if (AISAPI::isAvailable())
 			{
-				LLPointer<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
-				cmd_ptr->run_command();
+                AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+                AISAPI::PurgeDescendents(id, cr);
 			}
 			else // no cap
 			{
@@ -1780,27 +1786,20 @@ void copy_inventory_from_notecard(const LLUUID& destination_id,
         return;
     }
 
-	// check capability to prevent a crash while LL_ERRS in LLCapabilityListener::capListener. See EXT-8459.
-	std::string url = viewer_region->getCapability("CopyInventoryFromNotecard");
-	if (url.empty())
-	{
-        LL_WARNS(LOG_NOTECARD) << "There is no 'CopyInventoryFromNotecard' capability"
-							   << " for region: " << viewer_region->getName()
-							   << LL_ENDL;
-		return;
-	}
-
-    LLSD request, body;
+    LLSD body;
     body["notecard-id"] = notecard_inv_id;
     body["object-id"] = object_id;
     body["item-id"] = src->getUUID();
 	body["folder-id"] = destination_id;
     body["callback-id"] = (LLSD::Integer)callback_id;
 
-    request["message"] = "CopyInventoryFromNotecard";
-    request["payload"] = body;
-
-    viewer_region->getCapAPI().post(request);
+    /// *TODO: RIDER: This posts the request under the agents policy.  
+    /// When I convert the inventory over this call should be moved under that 
+    /// policy as well.
+    if (!gAgent.requestPostCapability("CopyInventoryFromNotecard", body))
+    {
+        LL_WARNS() << "SIM does not have the capability to copy from notecard." << LL_ENDL;
+    }
 }
 
 void create_new_item(const std::string& name,
@@ -1858,12 +1857,13 @@ void slam_inventory_folder(const LLUUID& folder_id,
 						   const LLSD& contents,
 						   LLPointer<LLInventoryCallback> cb)
 {
-	if (AISCommand::isAPIAvailable())
+    if (AISAPI::isAvailable())
 	{
 		LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id
 						   << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
-		LLPointer<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
-		cmd_ptr->run_command();
+
+        AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
+        AISAPI::SlamFolder(folder_id, contents, cr);
 	}
 	else // no cap
 	{
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 3eae0f8d86ca64d9d64ab29b43e0d91db409ed42..75a201d92f6cf6a165d782973375c1785cf41dea 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -69,6 +69,7 @@
 #include "llwebprofile.h"
 #include "llwindow.h"
 #include "llvieweraudio.h"
+#include "llcorehttputil.h"
 
 #include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
 
@@ -152,190 +153,6 @@ LLViewerMediaObserver::~LLViewerMediaObserver()
 }
 
 
-// Move this to its own file.
-// helper class that tries to download a URL from a web site and calls a method
-// on the Panel Land Media and to discover the MIME type
-class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLMimeDiscoveryResponder);
-public:
-	LLMimeDiscoveryResponder( viewer_media_t media_impl)
-		: mMediaImpl(media_impl),
-		  mInitialized(false)
-	{
-		if(mMediaImpl->mMimeTypeProbe != NULL)
-		{
-			LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL;
-		}
-		
-		mMediaImpl->mMimeTypeProbe = this;
-	}
-
-	~LLMimeDiscoveryResponder()
-	{
-		disconnectOwner();
-	}
-
-private:
-	/* virtual */ void httpCompleted()
-	{
-		if (!isGoodStatus())
-		{
-			LL_WARNS() << dumpResponse()
-					<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-		}
-		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
-		std::string::size_type idx1 = media_type.find_first_of(";");
-		std::string mime_type = media_type.substr(0, idx1);
-
-		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL;
-		
-		// 2xx status codes indicate success.
-		// Most 4xx status codes are successful enough for our purposes.
-		// 499 is the error code for host not found, timeout, etc.
-		// 500 means "Internal Server error" but we decided it's okay to 
-		//     accept this and go past it in the MIME type probe
-		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
-		// 499 is a code specifc to join.secondlife.com apparently safe to ignore
-//		if(	((status >= 200) && (status < 300))	||
-//			((status >= 400) && (status < 499))	|| 
-//			(status == 500) ||
-//			(status == 302) ||
-//			(status == 499) 
-//			)
-		// We now no longer check the error code returned from the probe.
-		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
-		//if(1)
-		{
-			// The probe was successful.
-			if(mime_type.empty())
-			{
-				// Some sites don't return any content-type header at all.
-				// Treat an empty mime type as text/html.
-				mime_type = HTTP_CONTENT_TEXT_HTML;
-			}
-		}
-		//else
-		//{
-		//	LL_WARNS() << "responder failed with status " << dumpResponse() << LL_ENDL;
-		//
-		//	if(mMediaImpl)
-		//	{
-		//		mMediaImpl->mMediaSourceFailed = true;
-		//	}
-		//	return;
-		//}
-
-		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
-		// Make a local copy so we can call loadURI() afterwards.
-		LLViewerMediaImpl *impl = mMediaImpl;
-		
-		if(impl && !mInitialized && ! mime_type.empty())
-		{
-			if(impl->initializeMedia(mime_type))
-			{
-				mInitialized = true;
-				impl->loadURI();
-				disconnectOwner();
-			}
-		}
-	}
-	
-public:
-	void cancelRequest()
-	{
-		disconnectOwner();
-	}
-	
-private:
-	void disconnectOwner()
-	{
-		if(mMediaImpl)
-		{
-			if(mMediaImpl->mMimeTypeProbe != this)
-			{
-				LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL;
-			}
-
-			mMediaImpl->mMimeTypeProbe = NULL;
-		}
-		mMediaImpl = NULL;
-	}
-	
-	
-public:
-		LLViewerMediaImpl *mMediaImpl;
-		bool mInitialized;
-};
-
-class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLViewerMediaOpenIDResponder);
-public:
-	LLViewerMediaOpenIDResponder( )
-	{
-	}
-
-	~LLViewerMediaOpenIDResponder()
-	{
-	}
-
-	/* virtual */ void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// We don't care about the content of the response, only the Set-Cookie header.
-		LL_DEBUGS("MediaAuth") << dumpResponse() 
-				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-		
-		// *TODO: What about bad status codes?  Does this destroy previous cookies?
-		LLViewerMedia::openIDCookieResponse(cookie);
-	}
-
-};
-
-class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
-{
-LOG_CLASS(LLViewerMediaWebProfileResponder);
-public:
-	LLViewerMediaWebProfileResponder(std::string host)
-	{
-		mHost = host;
-	}
-
-	~LLViewerMediaWebProfileResponder()
-	{
-	}
-
-	 void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// We don't care about the content of the response, only the set-cookie header.
-		LL_WARNS("MediaAuth") << dumpResponse() 
-				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-
-		LLSD stripped_content = getResponseHeaders();
-		// *TODO: Check that this works.
-		stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE);
-		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL;
-
-		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
-
-		// *TODO: What about bad status codes?  Does this destroy previous cookies?
-		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
-
-		// Set cookie for snapshot publishing.
-		std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path
-		LLWebProfile::setAuthCookie(auth_cookie);
-	}
-
-	std::string mHost;
-};
-
-
 LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
 LLURL LLViewerMedia::sOpenIDURL;
 std::string LLViewerMedia::sOpenIDCookie;
@@ -1388,87 +1205,172 @@ LLSD LLViewerMedia::getHeaders()
 	return headers;
 }
 
+LLCore::HttpHeaders::ptr_t LLViewerMedia::getHttpHeaders()
+{
+    LLCore::HttpHeaders::ptr_t headers(new LLCore::HttpHeaders);
+
+    headers->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_XML);
+    headers->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie);
+    headers->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent());
+
+    return headers;
+}
+
 /////////////////////////////////////////////////////////////////////////////////////////
 // static
 void LLViewerMedia::setOpenIDCookie()
 {
 	if(!sOpenIDCookie.empty())
 	{
-		// The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
-		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
-		// We therefore do it here.
-		std::string authority = sOpenIDURL.mAuthority;
-		std::string::size_type host_start = authority.find('@'); 
-		if(host_start == std::string::npos)
-		{
-			// no username/password
-			host_start = 0;
-		}
-		else
-		{
-			// Hostname starts after the @. 
-			// (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
-			++host_start;
-		}
-		std::string::size_type host_end = authority.rfind(':'); 
-		if((host_end == std::string::npos) || (host_end < host_start))
-		{
-			// no port
-			host_end = authority.size();
-		}
-		
-		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start));
+        std::string profileUrl = getProfileURL("");
+
+        LLCoros::instance().launch("LLViewerMedia::getOpenIDCookieCoro",
+            boost::bind(&LLViewerMedia::getOpenIDCookieCoro, profileUrl));
+	}
+}
+
+/*static*/
+void LLViewerMedia::getOpenIDCookieCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getOpenIDCookieCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    
+    httpOpts->setFollowRedirects(true);
+    httpOpts->setWantHeaders(true);
+
+    LLURL hostUrl(url.c_str());
+    std::string hostAuth = hostUrl.getAuthority();
+
+    // *TODO: Expand LLURL to split and extract this information better. 
+    // The structure of a URL is well defined and needing to retrieve parts of it are common.
+    // original comment:
+    // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
+    // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
+    // We therefore do it here.
+    std::string authority = sOpenIDURL.mAuthority;
+    std::string::size_type hostStart = authority.find('@');
+    if (hostStart == std::string::npos)
+    {   // no username/password
+        hostStart = 0;
+    }
+    else
+    {   // Hostname starts after the @. 
+        // (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
+        ++hostStart;
+    }
+    std::string::size_type hostEnd = authority.rfind(':');
+    if ((hostEnd == std::string::npos) || (hostEnd < hostStart))
+    {   // no port
+        hostEnd = authority.size();
+    }
 
-		// Do a web profile get so we can store the cookie 
-		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
-		headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
+    getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart));
 
-		std::string profile_url = getProfileURL("");
-		LLURL raw_profile_url( profile_url.c_str() );
+    // Do a web profile get so we can store the cookie 
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie);
+    httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent());
+
+
+    LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL;
+    LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
+    
+    LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("MediaAuth") << "Error getting web profile." << LL_ENDL;
+        return;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE))
+    {
+        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL;
+        return;
+    }
+
+    const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asStringRef();
+    LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
+
+    // *TODO: What about bad status codes?  Does this destroy previous cookies?
+    LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, hostAuth);
+
+    // Set cookie for snapshot publishing.
+    std::string authCookie = cookie.substr(0, cookie.find(";")); // strip path
+    LLWebProfile::setAuthCookie(authCookie);
 
-		LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL;
-		LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
-		LLHTTPClient::get(profile_url,  
-			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
-			headers);
-	}
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // static
-void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
+void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken)
 {
-	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
+	LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << LL_ENDL;
 
-	// post the token to the url 
-	// the responder will need to extract the cookie(s).
+    LLCoros::instance().launch("LLViewerMedia::openIDSetupCoro",
+        boost::bind(&LLViewerMedia::openIDSetupCoro, openidUrl, openidToken));
+}
 
-	// Save the OpenID URL for later -- we may need the host when adding the cookie.
-	sOpenIDURL.init(openid_url.c_str());
-	
-	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
-	sOpenIDCookie.clear();
+/*static*/
+void LLViewerMedia::openIDSetupCoro(std::string openidUrl, std::string openidToken)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("openIDSetupCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
 
-	LLSD headers = LLSD::emptyMap();
-	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
-
-	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
-	size_t size = openid_token.size();
-	U8 *data = new U8[size];
-	memcpy(data, openid_token.data(), size);
-
-	LLHTTPClient::postRaw( 
-		openid_url, 
-		data, 
-		size, 
-		new LLViewerMediaOpenIDResponder(),
-		headers);
-			
+    httpOpts->setWantHeaders(true);
+
+    // post the token to the url 
+    // the responder will need to extract the cookie(s).
+    // Save the OpenID URL for later -- we may need the host when adding the cookie.
+    sOpenIDURL.init(openidUrl.c_str());
+    // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
+    sOpenIDCookie.clear();
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded");
+
+    LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
+    LLCore::BufferArrayStream bas(rawbody.get());
+
+    bas << std::noskipws << openidToken;
+
+    LLSD result = httpAdapter->postRawAndSuspend(httpRequest, openidUrl, rawbody, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("MediaAuth") << "Error getting Open ID cookie" << LL_ENDL;
+        return;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE))
+    {
+        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL;
+        return;
+    }
+
+    // We don't care about the content of the response, only the Set-Cookie header.
+    const std::string &cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE];
+
+    // *TODO: What about bad status codes?  Does this destroy previous cookies?
+    LLViewerMedia::openIDCookieResponse(cookie);
+    LL_DEBUGS("MediaAuth") << "OpenID cookie set." << LL_ENDL;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -1661,7 +1563,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mIsParcelMedia(false),
 	mProximity(-1),
 	mProximityDistance(0.0f),
-	mMimeTypeProbe(NULL),
 	mMediaAutoPlay(false),
 	mInNearbyMediaList(false),
 	mClearCache(false),
@@ -1671,8 +1572,10 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mIsUpdated(false),
 	mTrustedBrowser(false),
 	mZoomFactor(1.0),
-    mCleanBrowser(false)
-{ 
+    mCleanBrowser(false),
+    mMimeProbe(),
+    mCanceling(false)
+{
 
 	// Set up the mute list observer if it hasn't been set up already.
 	if(!sViewerMediaMuteListObserverInitialized)
@@ -2610,7 +2513,8 @@ void LLViewerMediaImpl::navigateInternal()
 		return;
 	}
 	
-	if(mMimeTypeProbe != NULL)
+    
+    if (!mMimeProbe.expired())
 	{
 		LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;
 		return;
@@ -2648,14 +2552,8 @@ void LLViewerMediaImpl::navigateInternal()
 
 		if(scheme.empty() || "http" == scheme || "https" == scheme)
 		{
-			// If we don't set an Accept header, LLHTTPClient will add one like this:
-			//    Accept: application/llsd+xml
-			// which is really not what we want.
-			LLSD headers = LLSD::emptyMap();
-			headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers[HTTP_OUT_HEADER_COOKIE] = "";
-			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
+            LLCoros::instance().launch("LLViewerMediaImpl::mimeDiscoveryCoro",
+                boost::bind(&LLViewerMediaImpl::mimeDiscoveryCoro, this, mMediaURL));
 		}
 		else if("data" == scheme || "file" == scheme || "about" == scheme)
 		{
@@ -2685,6 +2583,66 @@ void LLViewerMediaImpl::navigateInternal()
 	}
 }
 
+void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("mimeDiscoveryCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    mMimeProbe = httpAdapter;
+
+    httpOpts->setFollowRedirects(true);
+    httpOpts->setHeadersOnly(true);
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, "");
+
+    LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+    mMimeProbe.reset();
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Error retrieving media headers." << LL_ENDL;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    
+    const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE].asStringRef();
+
+    std::string::size_type idx1 = mediaType.find_first_of(";");
+    std::string mimeType = mediaType.substr(0, idx1);
+
+    // We now no longer need to check the error code returned from the probe.
+    // If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
+    // The probe was successful.
+    if (mimeType.empty())
+    {
+        // Some sites don't return any content-type header at all.
+        // Treat an empty mime type as text/html.
+        mimeType = HTTP_CONTENT_TEXT_HTML;
+    }
+
+    LL_DEBUGS() << "Media type \"" << mediaType << "\", mime type is \"" << mimeType << "\"" << LL_ENDL;
+
+    // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+    // Make a local copy so we can call loadURI() afterwards.
+
+    if (!mimeType.empty())
+    {
+        if (initializeMedia(mimeType))
+        {
+            loadURI();
+        }
+    }
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::navigateStop()
 {
@@ -2783,7 +2741,7 @@ void LLViewerMediaImpl::update()
 		{
 			// Don't load new instances that are at PRIORITY_SLIDESHOW or below.  They're just kept around to preserve state.
 		}
-		else if(mMimeTypeProbe != NULL)
+        else if (!mMimeProbe.expired())
 		{
 			// this media source is doing a MIME type probe -- don't try loading it again.
 		}
@@ -3673,18 +3631,10 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
 
 void LLViewerMediaImpl::cancelMimeTypeProbe()
 {
-	if(mMimeTypeProbe != NULL)
-	{
-		// There doesn't seem to be a way to actually cancel an outstanding request.
-		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
-		mMimeTypeProbe->cancelRequest();
-		
-		// The above should already have set mMimeTypeProbe to NULL.
-		if(mMimeTypeProbe != NULL)
-		{
-			LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL;
-		}
-	}
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t probeAdapter = mMimeProbe.lock();
+
+    if (probeAdapter)
+        probeAdapter->cancelSuspendedOperation();
 }
 
 void LLViewerMediaImpl::addObject(LLVOVolume* obj) 
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 6803adfaa251bc986ff6a76aacebc9009f1f5e70..92d644c9008db5653149a7fde5adb6427e4b949f 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -40,6 +40,9 @@
 #include "llnotificationptr.h"
 
 #include "llurl.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llcorehttputil.h"
 
 class LLViewerMediaImpl;
 class LLUUID;
@@ -161,11 +164,15 @@ class LLViewerMedia
 	static void setOnlyAudibleMediaTextureID(const LLUUID& texture_id);
 
 	static LLSD getHeaders();
+    static LLCore::HttpHeaders::ptr_t getHttpHeaders();
 	
 private:
 	static void setOpenIDCookie();
 	static void onTeleportFinished();
-	
+
+    static void openIDSetupCoro(std::string openidUrl, std::string openidToken);
+    static void getOpenIDCookieCoro(std::string url);
+
 	static LLPluginCookieStore *sCookieStore;
 	static LLURL sOpenIDURL;
 	static std::string sOpenIDCookie;
@@ -180,7 +187,6 @@ class LLViewerMediaImpl
 public:
 	
 	friend class LLViewerMedia;
-	friend class LLMimeDiscoveryResponder;
 	
 	LLViewerMediaImpl(
 		const LLUUID& texture_id,
@@ -453,7 +459,6 @@ class LLViewerMediaImpl
 	S32 mProximity;
 	F64 mProximityDistance;
 	F64 mProximityCamera;
-	LLMimeDiscoveryResponder *mMimeTypeProbe;
 	bool mMediaAutoPlay;
 	std::string mMediaEntryURL;
 	bool mInNearbyMediaList;	// used by LLPanelNearbyMedia::refreshList() for performance reasons
@@ -470,6 +475,10 @@ class LLViewerMediaImpl
 	BOOL mIsUpdated ;
 	std::list< LLVOVolume* > mObjectList ;
 
+    void mimeDiscoveryCoro(std::string url);
+    LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mMimeProbe;
+    bool mCanceling;
+
 private:
 	LLViewerMediaTexture *updatePlaceholderImage();
 };
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2505ae6a9c2f655f46feb0b4b912a7cd4c637509..d8ec44b132ade1ca3ee84e2973be4a0db98a5a67 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -390,32 +390,10 @@ void set_underclothes_menu_options()
 
 void set_merchant_SLM_menu()
 {
-    // DD-170 : SLM Alpha and Beta program : for the moment, we always show the SLM menu and 
-    // tools so that all merchants can try out the UI, even if not migrated.
-    // *TODO : Keep SLM UI hidden for non migrated merchant in released viewer
-    
-    //if (LLMarketplaceData::instance().getSLMStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT)
-    //{
-        // Merchant not migrated: show only the old Merchant Outbox menu
-    //    gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE);
-    //}
-    //else
-    //{
-        // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool
-        gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(TRUE);
-        LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
-		gToolBarView->enableCommand(command->id(), true);
-    //}
-}
-
-void set_merchant_outbox_menu(U32 status, const LLSD& content)
-{
-    // If the merchant is fully migrated, the API is disabled (503) and we won't show the old menu item.
-    // In all other cases, we show it.
-    if (status != MarketplaceErrorCodes::IMPORT_SERVER_API_DISABLED)
-    {
-        gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE);
-    }
+    // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool
+    gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(TRUE);
+    LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
+	gToolBarView->enableCommand(command->id(), true);
 }
 
 void check_merchant_status()
@@ -434,17 +412,6 @@ void check_merchant_status()
         
         // Launch an SLM test connection to get the merchant status
         LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
-
-        // Do the Merchant Outbox init only once per session
-        if (LLMarketplaceInventoryImporter::instance().getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED)
-        {
-            // Hide merchant outbox related menu item
-            gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(FALSE);
-            
-            // Launch a Merchant Outbox test connection to get the migration status
-            LLMarketplaceInventoryImporter::instance().setStatusReportCallback(boost::bind(&set_merchant_outbox_menu,_1, _2));
-            LLMarketplaceInventoryImporter::instance().initialize();
-        }
     }
 }
 
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index f8e50ba463e616fff5f09006fdd3eade1967affb..4f24dfafac95e8bf776f18bcee562066f02299f2 100755
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -62,11 +62,10 @@
 #include "lluploaddialog.h"
 #include "lltrans.h"
 #include "llfloaterbuycurrency.h"
+#include "llviewerassetupload.h"
 
 // linden libraries
-#include "llassetuploadresponders.h"
 #include "lleconomy.h"
-#include "llhttpclient.h"
 #include "llnotificationsutil.h"
 #include "llsdserialize.h"
 #include "llsdutil.h"
@@ -83,8 +82,9 @@ class LLFileEnableUpload : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
-		return new_value;
+        return true;
+// 		bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
+// 		return new_value;
 	}
 };
 
@@ -410,7 +410,6 @@ class LLFileUploadBulk : public view_listener_t
 		}
 
 		// TODO:
-		// Iterate over all files
 		// Check extensions for uploadability, cost
 		// Check user balance for entire cost
 		// Charge user entire cost
@@ -422,37 +421,33 @@ class LLFileUploadBulk : public view_listener_t
 		LLFilePicker& picker = LLFilePicker::instance();
 		if (picker.getMultipleOpenFiles())
 		{
-			const std::string& filename = picker.getFirstFile();
-			std::string name = gDirUtilp->getBaseFileName(filename, true);
-			
-			std::string asset_name = name;
-			LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
-			LLStringUtil::replaceChar(asset_name, '|', '?');
-			LLStringUtil::stripNonprintable(asset_name);
-			LLStringUtil::trim(asset_name);
-			
-			std::string display_name = LLStringUtil::null;
-			LLAssetStorage::LLStoreAssetCallback callback = NULL;
-			S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-			void *userdata = NULL;
-
-			upload_new_resource(
-				filename,
-				asset_name,
-				asset_name,
-				0,
-				LLFolderType::FT_NONE,
-				LLInventoryType::IT_NONE,
-				LLFloaterPerms::getNextOwnerPerms("Uploads"),
-				LLFloaterPerms::getGroupPerms("Uploads"),
-				LLFloaterPerms::getEveryonePerms("Uploads"),
-				display_name,
-				callback,
-				expected_upload_cost,
-				userdata);
-
-			// *NOTE: Ew, we don't iterate over the file list here,
-			// we handle the next files in upload_done_callback()
+            std::string filename = picker.getFirstFile();
+            S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+
+            while (!filename.empty())
+            {
+                std::string name = gDirUtilp->getBaseFileName(filename, true);
+
+                std::string asset_name = name;
+                LLStringUtil::replaceNonstandardASCII( asset_name, '?' );
+                LLStringUtil::replaceChar(asset_name, '|', '?');
+                LLStringUtil::stripNonprintable(asset_name);
+                LLStringUtil::trim(asset_name);
+
+                LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+                    filename,
+                    asset_name,
+                    asset_name, 0,
+                    LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+                    LLFloaterPerms::getNextOwnerPerms("Uploads"),
+                    LLFloaterPerms::getGroupPerms("Uploads"),
+                    LLFloaterPerms::getEveryonePerms("Uploads"),
+                    expected_upload_cost));
+
+                upload_new_resource(uploadInfo, NULL, NULL);
+
+                filename = picker.getNextFile();
+            }
 		}
 		else
 		{
@@ -621,6 +616,7 @@ void handle_compress_image(void*)
 	}
 }
 
+
 LLUUID upload_new_resource(
 	const std::string& src_filename,
 	std::string name,
@@ -636,276 +632,16 @@ LLUUID upload_new_resource(
 	S32 expected_upload_cost,
 	void *userdata)
 {	
-	// Generate the temporary UUID.
-	std::string filename = gDirUtilp->getTempFilename();
-	LLTransactionID tid;
-	LLAssetID uuid;
-	
-	LLSD args;
-
-	std::string exten = gDirUtilp->getExtension(src_filename);
-	U32 codec = LLImageBase::getCodecFromExtension(exten);
-	LLAssetType::EType asset_type = LLAssetType::AT_NONE;
-	std::string error_message;
-
-	BOOL error = FALSE;
-	
-	if (exten.empty())
-	{
-		std::string short_name = gDirUtilp->getBaseFileName(filename);
-		
-		// No extension
-		error_message = llformat(
-				"No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
-				short_name.c_str());
-		args["FILE"] = short_name;
- 		upload_error(error_message, "NoFileExtension", filename, args);
-		return LLUUID();
-	}
-	else if (codec != IMG_CODEC_INVALID)
-	{
-		// It's an image file, the upload procedure is the same for all
-		asset_type = LLAssetType::AT_TEXTURE;
-		if (!LLViewerTextureList::createUploadFile(src_filename, filename, codec ))
-		{
-			error_message = llformat( "Problem with file %s:\n\n%s\n",
-									 src_filename.c_str(), LLImage::getLastError().c_str());
-			args["FILE"] = src_filename;
-			args["ERROR"] = LLImage::getLastError();
-			upload_error(error_message, "ProblemWithFile", filename, args);
-			return LLUUID();
-		}
-	}
-	else if(exten == "wav")
-	{
-		asset_type = LLAssetType::AT_SOUND;  // tag it as audio
-		S32 encode_result = 0;
-
-		LL_INFOS() << "Attempting to encode wav as an ogg file" << LL_ENDL;
-
-		encode_result = encode_vorbis_file(src_filename, filename);
-		
-		if (LLVORBISENC_NOERR != encode_result)
-		{
-			switch(encode_result)
-			{
-				case LLVORBISENC_DEST_OPEN_ERR:
-				    error_message = llformat( "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
-					args["FILE"] = filename;
-					upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args);
-					break;
-
-				default:	
-				  error_message = llformat("Unknown vorbis encode failure on: %s\n", src_filename.c_str());
-					args["FILE"] = src_filename;
-					upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
-					break;	
-			}	
-			return LLUUID();
-		}
-	}
-	else if(exten == "tmp")	 	
-	{	 	
-		// This is a generic .lin resource file	 	
-         asset_type = LLAssetType::AT_OBJECT;	 	
-         LLFILE* in = LLFile::fopen(src_filename, "rb");		/* Flawfinder: ignore */	 	
-         if (in)	 	
-         {	 	
-                 // read in the file header	 	
-                 char buf[16384];		/* Flawfinder: ignore */ 	
-                 size_t readbytes;
-                 S32  version;	 	
-                 if (fscanf(in, "LindenResource\nversion %d\n", &version))	 	
-                 {	 	
-                         if (2 == version)	 	
-                         {
-								// *NOTE: This buffer size is hard coded into scanf() below.
-                                 char label[MAX_STRING];		/* Flawfinder: ignore */	 	
-                                 char value[MAX_STRING];		/* Flawfinder: ignore */	 	
-                                 S32  tokens_read;	 	
-                                 while (fgets(buf, 1024, in))	 	
-                                 {	 	
-                                         label[0] = '\0';	 	
-                                         value[0] = '\0';	 	
-                                         tokens_read = sscanf(	/* Flawfinder: ignore */
-											 buf,
-											 "%254s %254s\n",
-											 label, value);	 	
-
-                                         LL_INFOS() << "got: " << label << " = " << value	 	
-                                                         << LL_ENDL;	 	
-
-                                         if (EOF == tokens_read)	 	
-                                         {	 	
-                                                 fclose(in);	 	
-                                                 error_message = llformat("corrupt resource file: %s", src_filename.c_str());
-												 args["FILE"] = src_filename;
-												 upload_error(error_message, "CorruptResourceFile", filename, args);
-                                                 return LLUUID();
-                                         }	 	
-
-                                         if (2 == tokens_read)	 	
-                                         {	 	
-                                                 if (! strcmp("type", label))	 	
-                                                 {	 	
-                                                         asset_type = (LLAssetType::EType)(atoi(value));	 	
-                                                 }	 	
-                                         }	 	
-                                         else	 	
-                                         {	 	
-                                                 if (! strcmp("_DATA_", label))	 	
-                                                 {	 	
-                                                         // below is the data section	 	
-                                                         break;	 	
-                                                 }	 	
-                                         }	 	
-                                         // other values are currently discarded	 	
-                                 }	 	
-
-                         }	 	
-                         else	 	
-                         {	 	
-                                 fclose(in);	 	
-                                 error_message = llformat("unknown linden resource file version in file: %s", src_filename.c_str());
-								 args["FILE"] = src_filename;
-								 upload_error(error_message, "UnknownResourceFileVersion", filename, args);
-                                 return LLUUID();
-                         }	 	
-                 }	 	
-                 else	 	
-                 {	 	
-                         // this is an original binary formatted .lin file	 	
-                         // start over at the beginning of the file	 	
-                         fseek(in, 0, SEEK_SET);	 	
-
-                         const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256;	 	
-                         const S32 MAX_ASSET_NAME_LENGTH = 64;	 	
-                         S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH;	 	
-                         S16     type_num;	 	
-
-                         // read in and throw out most of the header except for the type	 	
-                         if (fread(buf, header_size, 1, in) != 1)
-						 {
-							 LL_WARNS() << "Short read" << LL_ENDL;
-						 }
-                         memcpy(&type_num, buf + 16, sizeof(S16));		/* Flawfinder: ignore */	 	
-                         asset_type = (LLAssetType::EType)type_num;	 	
-                 }	 	
-
-                 // copy the file's data segment into another file for uploading	 	
-                 LLFILE* out = LLFile::fopen(filename, "wb");		/* Flawfinder: ignore */	
-                 if (out)	 	
-                 {	 	
-                         while((readbytes = fread(buf, 1, 16384, in)))		/* Flawfinder: ignore */	 	
-                         {	 	
-							 if (fwrite(buf, 1, readbytes, out) != readbytes)
-							 {
-								 LL_WARNS() << "Short write" << LL_ENDL;
-							 }
-                         }	 	
-                         fclose(out);	 	
-                 }	 	
-                 else	 	
-                 {	 	
-                         fclose(in);	 	
-                         error_message = llformat( "Unable to create output file: %s", filename.c_str());
-						 args["FILE"] = filename;
-						 upload_error(error_message, "UnableToCreateOutputFile", filename, args);
-                         return LLUUID();
-                 }	 	
-
-                 fclose(in);	 	
-         }	 	
-         else	 	
-         {	 	
-                 LL_INFOS() << "Couldn't open .lin file " << src_filename << LL_ENDL;	 	
-         }	 	
-	}
-	else if (exten == "bvh")
-	{
-		error_message = llformat("We do not currently support bulk upload of animation files\n");
-		upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
-		return LLUUID();
-	}
-	else if (exten == "anim")
-	{
-		asset_type = LLAssetType::AT_ANIMATION;
-		filename = src_filename;
-	}
-	else
-	{
-		// Unknown extension
-		error_message = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
-		error = TRUE;;
-	}
-
-	// gen a new transaction ID for this asset
-	tid.generate();
 
-	if (!error)
-	{
-		uuid = tid.makeAssetID(gAgent.getSecureSessionID());
-		// copy this file into the vfs for upload
-		S32 file_size;
-		LLAPRFile infile ;
-		infile.open(filename, LL_APR_RB, NULL, &file_size);
-		if (infile.getFileHandle())
-		{
-			LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE);
-
-			file.setMaxSize(file_size);
-
-			const S32 buf_size = 65536;
-			U8 copy_buf[buf_size];
-			while ((file_size = infile.read(copy_buf, buf_size)))
-			{
-				file.write(copy_buf, file_size);
-			}
-		}
-		else
-		{
-			error_message = llformat( "Unable to access output file: %s", filename.c_str());
-			error = TRUE;
-		}
-	}
-
-	if (!error)
-	{
-		std::string t_disp_name = display_name;
-		if (t_disp_name.empty())
-		{
-			t_disp_name = src_filename;
-		}
-		upload_new_resource(
-			tid,
-			asset_type,
-			name,
-			desc,
-			compression_info, // tid
-			destination_folder_type,
-			inv_type,
-			next_owner_perms,
-			group_perms,
-			everyone_perms,
-			display_name,
-			callback,
-			expected_upload_cost,
-			userdata);
-	}
-	else
-	{
-		LL_WARNS() << error_message << LL_ENDL;
-		LLSD args;
-		args["ERROR_MESSAGE"] = error_message;
-		LLNotificationsUtil::add("ErrorMessage", args);
-		if(LLFile::remove(filename) == -1)
-		{
-			LL_DEBUGS() << "unable to remove temp file" << LL_ENDL;
-		}
-		LLFilePicker::instance().reset();
-	}
+    LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+        src_filename,
+        name, desc, compression_info,
+        destination_folder_type, inv_type,
+        next_owner_perms, group_perms, everyone_perms,
+        expected_upload_cost));
+    upload_new_resource(uploadInfo, callback, userdata);
 
-	return uuid;
+    return LLUUID::null;
 }
 
 void upload_done_callback(
@@ -1035,189 +771,62 @@ void upload_done_callback(
 	}
 }
 
-static LLAssetID upload_new_resource_prep(
-	const LLTransactionID& tid,
-	LLAssetType::EType asset_type,
-	LLInventoryType::EType& inventory_type,
-	std::string& name,
-	const std::string& display_name,
-	std::string& description)
-{
-	LLAssetID uuid = generate_asset_id_for_new_upload(tid);
-
-	increase_new_upload_stats(asset_type);
-
-	assign_defaults_and_show_upload_message(
-		asset_type,
-		inventory_type,
-		name,
-		display_name,
-		description);
-
-	return uuid;
-}
-
-LLSD generate_new_resource_upload_capability_body(
-	LLAssetType::EType asset_type,
-	const std::string& name,
-	const std::string& desc,
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms)
-{
-	LLSD body;
-
-	body["folder_id"] = gInventory.findCategoryUUIDForType(
-		(destination_folder_type == LLFolderType::FT_NONE) ?
-		(LLFolderType::EType) asset_type :
-		destination_folder_type);
-
-	body["asset_type"] = LLAssetType::lookup(asset_type);
-	body["inventory_type"] = LLInventoryType::lookup(inv_type);
-	body["name"] = name;
-	body["description"] = desc;
-	body["next_owner_mask"] = LLSD::Integer(next_owner_perms);
-	body["group_mask"] = LLSD::Integer(group_perms);
-	body["everyone_mask"] = LLSD::Integer(everyone_perms);
-
-	return body;
-}
-
 void upload_new_resource(
-	const LLTransactionID &tid,
-	LLAssetType::EType asset_type,
-	std::string name,
-	std::string desc,
-	S32 compression_info,
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms,
-	const std::string& display_name,
-	LLAssetStorage::LLStoreAssetCallback callback,
-	S32 expected_upload_cost,
-	void *userdata)
+    LLResourceUploadInfo::ptr_t &uploadInfo,
+    LLAssetStorage::LLStoreAssetCallback callback,
+    void *userdata)
 {
 	if(gDisconnected)
 	{
 		return ;
 	}
-	
-	LLAssetID uuid = 
-		upload_new_resource_prep(
-			tid,
-			asset_type,
-			inv_type,
-			name,
-			display_name,
-			desc);
-	
-	if( LLAssetType::AT_SOUND == asset_type )
-	{
-		add(LLStatViewer::UPLOAD_SOUND, 1);
-	}
-	else
-	if( LLAssetType::AT_TEXTURE == asset_type )
-	{
-		add(LLStatViewer::UPLOAD_TEXTURE, 1);
-	}
-	else
-	if( LLAssetType::AT_ANIMATION == asset_type)
-	{
-		add(LLStatViewer::ANIMATION_UPLOADS, 1);
-	}
 
-	if(LLInventoryType::IT_NONE == inv_type)
-	{
-		inv_type = LLInventoryType::defaultForAssetType(asset_type);
-	}
-	LLStringUtil::stripNonprintable(name);
-	LLStringUtil::stripNonprintable(desc);
-	if(name.empty())
-	{
-		name = "(No Name)";
-	}
-	if(desc.empty())
-	{
-		desc = "(No Description)";
-	}
-	
-	// At this point, we're ready for the upload.
-	std::string upload_message = "Uploading...\n\n";
-	upload_message.append(display_name);
-	LLUploadDialog::modalUploadDialog(upload_message);
-
-	LL_INFOS() << "*** Uploading: " << LL_ENDL;
-	LL_INFOS() << "Type: " << LLAssetType::lookup(asset_type) << LL_ENDL;
-	LL_INFOS() << "UUID: " << uuid << LL_ENDL;
-	LL_INFOS() << "Name: " << name << LL_ENDL;
-	LL_INFOS() << "Desc: " << desc << LL_ENDL;
-	LL_INFOS() << "Expected Upload Cost: " << expected_upload_cost << LL_ENDL;
-	LL_DEBUGS() << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << LL_ENDL;
-	LL_DEBUGS() << "Asset Type: " << LLAssetType::lookup(asset_type) << LL_ENDL;
-
-	std::string url = gAgent.getRegion()->getCapability(
-		"NewFileAgentInventory");
+//     uploadInfo->setAssetType(assetType);
+//     uploadInfo->setTransactionId(tid);
+
+
+	std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
 
 	if ( !url.empty() )
 	{
-		LL_INFOS() << "New Agent Inventory via capability" << LL_ENDL;
-
-		LLSD body;
-		body = generate_new_resource_upload_capability_body(
-			asset_type,
-			name,
-			desc,
-			destination_folder_type,
-			inv_type,
-			next_owner_perms,
-			group_perms,
-			everyone_perms);
-
-		LLHTTPClient::post(
-			url,
-			body,
-			new LLNewAgentInventoryResponder(
-				body,
-				uuid,
-				asset_type));
+        LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
 	}
 	else
 	{
+        uploadInfo->prepareUpload();
+        uploadInfo->logPreparedUpload();
+
 		LL_INFOS() << "NewAgentInventory capability not found, new agent inventory via asset system." << LL_ENDL;
 		// check for adequate funds
 		// TODO: do this check on the sim
-		if (LLAssetType::AT_SOUND == asset_type ||
-			LLAssetType::AT_TEXTURE == asset_type ||
-			LLAssetType::AT_ANIMATION == asset_type)
+		if (LLAssetType::AT_SOUND == uploadInfo->getAssetType() ||
+            LLAssetType::AT_TEXTURE == uploadInfo->getAssetType() ||
+            LLAssetType::AT_ANIMATION == uploadInfo->getAssetType())
 		{
 			S32 balance = gStatusBar->getBalance();
-			if (balance < expected_upload_cost)
+			if (balance < uploadInfo->getExpectedUploadCost())
 			{
 				// insufficient funds, bail on this upload
 				LLStringUtil::format_map_t args;
-				args["NAME"] = name;
-				args["AMOUNT"] = llformat("%d", expected_upload_cost);
-				LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost );
+				args["NAME"] = uploadInfo->getName();
+                args["AMOUNT"] = llformat("%d", uploadInfo->getExpectedUploadCost());
+                LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), uploadInfo->getExpectedUploadCost());
 				return;
 			}
 		}
 
 		LLResourceData* data = new LLResourceData;
-		data->mAssetInfo.mTransactionID = tid;
-		data->mAssetInfo.mUuid = uuid;
-		data->mAssetInfo.mType = asset_type;
+		data->mAssetInfo.mTransactionID = uploadInfo->getTransactionId();
+		data->mAssetInfo.mUuid = uploadInfo->getAssetId();
+        data->mAssetInfo.mType = uploadInfo->getAssetType();
 		data->mAssetInfo.mCreatorID = gAgentID;
-		data->mInventoryType = inv_type;
-		data->mNextOwnerPerm = next_owner_perms;
-		data->mExpectedUploadCost = expected_upload_cost;
+		data->mInventoryType = uploadInfo->getInventoryType();
+		data->mNextOwnerPerm = uploadInfo->getNextOwnerPerms();
+		data->mExpectedUploadCost = uploadInfo->getExpectedUploadCost();
 		data->mUserData = userdata;
-		data->mAssetInfo.setName(name);
-		data->mAssetInfo.setDescription(desc);
-		data->mPreferredLocation = destination_folder_type;
+		data->mAssetInfo.setName(uploadInfo->getName());
+		data->mAssetInfo.setDescription(uploadInfo->getDescription());
+		data->mPreferredLocation = uploadInfo->getDestinationFolderType();
 
 		LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback;
 		if (callback)
@@ -1233,66 +842,6 @@ void upload_new_resource(
 	}
 }
 
-LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)
-{
-	if ( gDisconnected )
-	{	
-		LLAssetID rv;
-
-		rv.setNull();
-		return rv;
-	}
-
-	LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
-
-	return uuid;
-}
-
-void increase_new_upload_stats(LLAssetType::EType asset_type)
-{
-	if ( LLAssetType::AT_SOUND == asset_type )
-	{
-		add(LLStatViewer::UPLOAD_SOUND, 1);
-	}
-	else if ( LLAssetType::AT_TEXTURE == asset_type )
-	{
-		add(LLStatViewer::UPLOAD_TEXTURE, 1);
-	}
-	else if ( LLAssetType::AT_ANIMATION == asset_type )
-	{
-		add(LLStatViewer::ANIMATION_UPLOADS, 1);
-	}
-}
-
-void assign_defaults_and_show_upload_message(
-	LLAssetType::EType asset_type,
-	LLInventoryType::EType& inventory_type,
-	std::string& name,
-	const std::string& display_name,
-	std::string& description)
-{
-	if ( LLInventoryType::IT_NONE == inventory_type )
-	{
-		inventory_type = LLInventoryType::defaultForAssetType(asset_type);
-	}
-	LLStringUtil::stripNonprintable(name);
-	LLStringUtil::stripNonprintable(description);
-
-	if ( name.empty() )
-	{
-		name = "(No Name)";
-	}
-	if ( description.empty() )
-	{
-		description = "(No Description)";
-	}
-
-	// At this point, we're ready for the upload.
-	std::string upload_message = "Uploading...\n\n";
-	upload_message.append(display_name);
-	LLUploadDialog::modalUploadDialog(upload_message);
-}
-
 
 void init_menu_file()
 {
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 3034d00b22ef4202d7cf4dddf4036198269effe7..6941b4dc0e762191bc42e3a63ec483d0daa50846 100755
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -34,45 +34,35 @@
 #include "llthread.h"
 #include <queue>
 
+#include "llviewerassetupload.h"
+
 class LLTransactionID;
 
 
 void init_menu_file();
 
+
 LLUUID upload_new_resource(
-	const std::string& src_filename, 
-	std::string name,
-	std::string desc, 
-	S32 compression_info,
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms,
-	const std::string& display_name,
-	LLAssetStorage::LLStoreAssetCallback callback,
-	S32 expected_upload_cost,
-	void *userdata);
+    const std::string& src_filename,
+    std::string name,
+    std::string desc,
+    S32 compression_info,
+    LLFolderType::EType destination_folder_type,
+    LLInventoryType::EType inv_type,
+    U32 next_owner_perms,
+    U32 group_perms,
+    U32 everyone_perms,
+    const std::string& display_name,
+    LLAssetStorage::LLStoreAssetCallback callback,
+    S32 expected_upload_cost,
+    void *userdata);
 
 void upload_new_resource(
-	const LLTransactionID &tid, 
-	LLAssetType::EType type,
-	std::string name,
-	std::string desc, 
-	S32 compression_info,
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms,
-	const std::string& display_name,
-	LLAssetStorage::LLStoreAssetCallback callback,
-	S32 expected_upload_cost,
-	void *userdata);
+    LLResourceUploadInfo::ptr_t &uploadInfo,
+    LLAssetStorage::LLStoreAssetCallback callback = NULL,
+    void *userdata = NULL);
 
 
-LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);
-void increase_new_upload_stats(LLAssetType::EType asset_type);
 void assign_defaults_and_show_upload_message(
 	LLAssetType::EType asset_type,
 	LLInventoryType::EType& inventory_type,
@@ -80,26 +70,6 @@ void assign_defaults_and_show_upload_message(
 	const std::string& display_name,
 	std::string& description);
 
-LLSD generate_new_resource_upload_capability_body(
-	LLAssetType::EType asset_type,
-	const std::string& name,
-	const std::string& desc,
-	LLFolderType::EType destination_folder_type,
-	LLInventoryType::EType inv_type,
-	U32 next_owner_perms,
-	U32 group_perms,
-	U32 everyone_perms);
-
-void on_new_single_inventory_upload_complete(
-	LLAssetType::EType asset_type,
-	LLInventoryType::EType inventory_type,
-	const std::string inventory_type_string,
-	const LLUUID& item_folder_id,
-	const std::string& item_name,
-	const std::string& item_description,
-	const LLSD& server_response,
-	S32 upload_price);
-
 class LLFilePickerThread : public LLThread
 { //multi-threaded file picker (runs system specific file picker in background and calls "notify" from main thread)
 public:
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 886725be7912e4d195db604e9a68f9eb57c76196..4062228ae55fbea87409a093852b9f3ab9a82868 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -120,6 +120,8 @@
 #include "llnotificationmanager.h" //
 #include "llexperiencecache.h"
 
+#include "llexperiencecache.h"
+
 #if LL_MSVC
 // disable boost::lexical_cast warning
 #pragma warning (disable:4702)
@@ -3490,53 +3492,29 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
 	LLNotificationsUtil::add("CallingCardDeclined");
 }
 
-class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
+void translateSuccess(LLChat chat, LLSD toastArgs, std::string originalMsg, std::string expectLang, std::string translation, const std::string detected_language)
 {
-public :
-	ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, const std::string &mesg,
-							const LLChat &chat, const LLSD &toast_args)
-		: LLTranslate::TranslationReceiver(from_lang, to_lang),
-		m_chat(chat),
-		m_toastArgs(toast_args),
-		m_origMesg(mesg)
-	{
-	}
-
-	static ChatTranslationReceiver* build(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, const LLChat &chat, const LLSD &toast_args)
-	{
-		return new ChatTranslationReceiver(from_lang, to_lang, mesg, chat, toast_args);
-	}
-
-protected:
-	void handleResponse(const std::string &translation, const std::string &detected_language)
-	{
-		// filter out non-interesting responeses
-		if ( !translation.empty()
-			&& (mToLang != detected_language)
-			&& (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
-		{
-			m_chat.mText += " (" + translation + ")";
-		}
+    // filter out non-interesting responses  
+    if (!translation.empty()
+        && (expectLang != detected_language)
+        && (LLStringUtil::compareInsensitive(translation, originalMsg) != 0))
+    {
+        chat.mText += " (" + translation + ")";
+    }
 
-		LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
-	}
+    LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
+}
 
-	void handleFailure(int status, const std::string& err_msg)
-	{
-		LL_WARNS() << "Translation failed for mesg " << m_origMesg << " toLang " << mToLang << " fromLang " << mFromLang << LL_ENDL;
+void translateFailure(LLChat chat, LLSD toastArgs, int status, const std::string err_msg)
+{
+    std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
+    LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
+    chat.mText += " (" + msg + ")";
 
-		std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
-		LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
-		m_chat.mText += " (" + msg + ")";
+    LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
+}
 
-		LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
-	}
 
-private:
-	LLChat m_chat;
-	std::string m_origMesg;
-	LLSD m_toastArgs;		
-};
 void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 {
 	LLChat	chat;
@@ -3772,8 +3750,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 			const std::string from_lang = ""; // leave empty to trigger autodetect
 			const std::string to_lang = LLTranslate::getTranslateLanguage();
 
-			LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
-			LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
+            LLTranslate::translateMessage(from_lang, to_lang, mesg,
+                boost::bind(&translateSuccess, chat, args, mesg, from_lang, _1, _2),
+                boost::bind(&translateFailure, chat, args, _1, _2));
+
 		}
 		else
 		{
@@ -6468,17 +6448,14 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
 			if (!region)
 			    return false;
 
-			std::string lookup_url=region->getCapability("ExperiencePreferences"); 
-			if(lookup_url.empty())
-				return false;
-			LLSD permission;
-			LLSD data;
-			permission["permission"]="Block";
+            LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), LLExperienceCache::ExperienceGetFn_t());
 
-			data[experience.asString()]=permission;
-			LLHTTPClient::put(lookup_url, data, NULL);
-			data["experience"]=experience;
-			LLEventPumps::instance().obtain("experience_permission").post(data);
+            LLSD permission;
+            LLSD data;
+            permission["permission"] = "Block";
+            data[experience.asString()] = permission;
+            data["experience"] = experience;
+            LLEventPumps::instance().obtain("experience_permission").post(data);
 		}
 }
 	return false;
@@ -6653,7 +6630,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
 			else if(experienceid.notNull())
 			{
 				payload["experience"]=experienceid;
-				LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
+                LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
 				return;
 			}
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index ac3f07fcd8a2c8fcdc2ca9145f00cb324fbc3880..190102ff0fbea3bde7fbdfe850c4323ada79b5df 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4437,21 +4437,21 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid)
 {
 	// Invalid host == get from the agent's sim
 	LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(
-		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid);
+		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost());
 	return setTETextureCore(te,image);
 }
 
 S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid)
 {
 	LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture(
-		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid);
+		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost());
 	return setTENormalMapCore(te, image);
 }
 
 S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid)
 {
 	LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture(
-		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid);
+		uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost());
 	return setTESpecularMapCore(te, image);
 }
 
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 75732a1e1911f97de6f0598a3fade8855e733279..5f01cdbb6fddb45a9d23950d1d21c0ad906c8c65 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -78,6 +78,10 @@
 #include "llappviewer.h"
 #include "llfloaterperms.h"
 #include "llvocache.h"
+#include "llcorehttputil.h"
+
+#include <algorithm>
+#include <iterator>
 
 extern F32 gMinObjectDistance;
 extern BOOL gAnimateTextures;
@@ -795,190 +799,6 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 	LLVOAvatar::cullAvatarsByPixelArea();
 }
 
-class LLObjectCostResponder : public LLCurl::Responder
-{
-	LOG_CLASS(LLObjectCostResponder);
-public:
-	LLObjectCostResponder(const LLSD& object_ids)
-		: mObjectIDs(object_ids)
-	{
-	}
-
-	// Clear's the global object list's pending
-	// request list for all objects requested
-	void clear_object_list_pending_requests()
-	{
-		// TODO*: No more hard coding
-		for (
-			LLSD::array_iterator iter = mObjectIDs.beginArray();
-			iter != mObjectIDs.endArray();
-			++iter)
-		{
-			gObjectList.onObjectCostFetchFailure(iter->asUUID());
-		}
-	}
-
-private:
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-
-		// TODO*: Error message to user
-		// For now just clear the request from the pending list
-		clear_object_list_pending_requests();
-	}
-
-	/* virtual */ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if ( !content.isMap() || content.has("error") )
-		{
-			// Improper response or the request had an error,
-			// show an error to the user?
-			LL_WARNS()
-				<< "Application level error when fetching object "
-				<< "cost.  Message: " << content["error"]["message"].asString()
-				<< ", identifier: " << content["error"]["identifier"].asString()
-				<< LL_ENDL;
-
-			// TODO*: Adaptively adjust request size if the
-			// service says we've requested too many and retry
-
-			// TODO*: Error message if not retrying
-			clear_object_list_pending_requests();
-			return;
-		}
-
-		// Success, grab the resource cost and linked set costs
-		// for an object if one was returned
-		for (
-			LLSD::array_iterator iter = mObjectIDs.beginArray();
-			iter != mObjectIDs.endArray();
-			++iter)
-		{
-			LLUUID object_id = iter->asUUID();
-
-			// Check to see if the request contains data for the object
-			if ( content.has(iter->asString()) )
-			{
-				F32 link_cost =
-					content[iter->asString()]["linked_set_resource_cost"].asReal();
-				F32 object_cost =
-					content[iter->asString()]["resource_cost"].asReal();
-
-				F32 physics_cost = content[iter->asString()]["physics_cost"].asReal();
-				F32 link_physics_cost = content[iter->asString()]["linked_set_physics_cost"].asReal();
-
-				gObjectList.updateObjectCost(object_id, object_cost, link_cost, physics_cost, link_physics_cost);
-			}
-			else
-			{
-				// TODO*: Give user feedback about the missing data?
-				gObjectList.onObjectCostFetchFailure(object_id);
-			}
-		}
-	}
-
-private:
-	LLSD mObjectIDs;
-};
-
-
-class LLPhysicsFlagsResponder : public LLCurl::Responder
-{
-	LOG_CLASS(LLPhysicsFlagsResponder);
-public:
-	LLPhysicsFlagsResponder(const LLSD& object_ids)
-		: mObjectIDs(object_ids)
-	{
-	}
-
-	// Clear's the global object list's pending
-	// request list for all objects requested
-	void clear_object_list_pending_requests()
-	{
-		// TODO*: No more hard coding
-		for (
-			LLSD::array_iterator iter = mObjectIDs.beginArray();
-			iter != mObjectIDs.endArray();
-			++iter)
-		{
-			gObjectList.onPhysicsFlagsFetchFailure(iter->asUUID());
-		}
-	}
-
-private:
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-
-		// TODO*: Error message to user
-		// For now just clear the request from the pending list
-		clear_object_list_pending_requests();
-	}
-
-	/* virtual void */ void httpSuccess()
-	{
-		const LLSD& content = getContent();
-		if ( !content.isMap() || content.has("error") )
-		{
-			// Improper response or the request had an error,
-			// show an error to the user?
-			LL_WARNS()
-				<< "Application level error when fetching object "
-				<< "physics flags.  Message: " << content["error"]["message"].asString()
-				<< ", identifier: " << content["error"]["identifier"].asString()
-				<< LL_ENDL;
-
-			// TODO*: Adaptively adjust request size if the
-			// service says we've requested too many and retry
-
-			// TODO*: Error message if not retrying
-			clear_object_list_pending_requests();
-			return;
-		}
-
-		// Success, grab the resource cost and linked set costs
-		// for an object if one was returned
-		for (
-			LLSD::array_iterator iter = mObjectIDs.beginArray();
-			iter != mObjectIDs.endArray();
-			++iter)
-		{
-			LLUUID object_id = iter->asUUID();
-
-			// Check to see if the request contains data for the object
-			if ( content.has(iter->asString()) )
-			{
-				const LLSD& data = content[iter->asString()];
-
-				S32 shape_type = data["PhysicsShapeType"].asInteger();
-
-				gObjectList.updatePhysicsShapeType(object_id, shape_type);
-
-				if (data.has("Density"))
-				{
-					F32 density = data["Density"].asReal();
-					F32 friction = data["Friction"].asReal();
-					F32 restitution = data["Restitution"].asReal();
-					F32 gravity_multiplier = data["GravityMultiplier"].asReal();
-					
-					gObjectList.updatePhysicsProperties(object_id, 
-						density, friction, restitution, gravity_multiplier);
-				}
-			}
-			else
-			{
-				// TODO*: Give user feedback about the missing data?
-				gObjectList.onPhysicsFlagsFetchFailure(object_id);
-			}
-		}
-	}
-
-private:
-	LLSD mObjectIDs;
-};
-
 static LLTrace::BlockTimerStatHandle FTM_IDLE_COPY("Idle Copy");
 
 void LLViewerObjectList::update(LLAgent &agent)
@@ -1174,41 +994,8 @@ void LLViewerObjectList::fetchObjectCosts()
 
 			if (!url.empty())
 			{
-				LLSD id_list;
-				U32 object_index = 0;
-
-				for (
-					std::set<LLUUID>::iterator iter = mStaleObjectCost.begin();
-					iter != mStaleObjectCost.end();
-					)
-				{
-					// Check to see if a request for this object
-					// has already been made.
-					if ( mPendingObjectCost.find(*iter) ==
-						 mPendingObjectCost.end() )
-					{
-						mPendingObjectCost.insert(*iter);
-						id_list[object_index++] = *iter;
-					}
-
-					mStaleObjectCost.erase(iter++);
-
-					if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS)
-					{
-						break;
-					}
-				}
-									
-				if ( id_list.size() > 0 )
-				{
-					LLSD post_data = LLSD::emptyMap();
-
-					post_data["object_ids"] = id_list;
-					LLHTTPClient::post(
-						url,
-						post_data,
-						new LLObjectCostResponder(id_list));
-				}
+                LLCoros::instance().launch("LLViewerObjectList::fetchObjectCostsCoro",
+                    boost::bind(&LLViewerObjectList::fetchObjectCostsCoro, this, url));
 			}
 			else
 			{
@@ -1219,6 +1006,107 @@ void LLViewerObjectList::fetchObjectCosts()
 	}
 }
 
+/*static*/
+void LLViewerObjectList::reportObjectCostFailure(LLSD &objectList)
+{
+    // TODO*: No more hard coding
+    for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it)
+    {
+        gObjectList.onObjectCostFetchFailure(it->asUUID());
+    }
+}
+
+
+void LLViewerObjectList::fetchObjectCostsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+
+
+    uuid_set_t diff;
+
+    std::set_difference(mStaleObjectCost.begin(), mStaleObjectCost.end(),
+        mPendingObjectCost.begin(), mPendingObjectCost.end(), 
+        std::inserter(diff, diff.begin()));
+
+    if (diff.empty())
+    {
+        LL_INFOS() << "No outstanding object IDs to request." << LL_ENDL;
+        return;
+    }
+
+    LLSD idList(LLSD::emptyArray());
+
+    for (uuid_set_t::iterator it = diff.begin(); it != diff.end(); ++it)
+    {
+        idList.append(*it);
+        mStaleObjectCost.erase(*it);
+    }
+
+    mPendingObjectCost.insert(diff.begin(), diff.end());
+
+    LLSD postData = LLSD::emptyMap();
+
+    postData["object_ids"] = idList;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status || result.has("error"))
+    {
+        if (result.has("error"))
+        {
+            LL_WARNS() << "Application level error when fetching object "
+                << "cost.  Message: " << result["error"]["message"].asString()
+                << ", identifier: " << result["error"]["identifier"].asString()
+                << LL_ENDL;
+
+            // TODO*: Adaptively adjust request size if the
+            // service says we've requested too many and retry
+        }
+        reportObjectCostFailure(idList);
+
+        return;
+    }
+
+    // Success, grab the resource cost and linked set costs
+    // for an object if one was returned
+    for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it)
+    {
+        LLUUID objectId = it->asUUID();
+
+        // If the object was added to the StaleObjectCost set after it had been 
+        // added to mPendingObjectCost it would still be in the StaleObjectCost 
+        // set when we got the response back.
+        mStaleObjectCost.erase(objectId);
+        mPendingObjectCost.erase(objectId);
+
+        // Check to see if the request contains data for the object
+        if (result.has(it->asString()))
+        {
+            LLSD objectData = result[it->asString()];
+
+            F32 linkCost = objectData["linked_set_resource_cost"].asReal();
+            F32 objectCost = objectData["resource_cost"].asReal();
+            F32 physicsCost = objectData["physics_cost"].asReal();
+            F32 linkPhysicsCost = objectData["linked_set_physics_cost"].asReal();
+
+            gObjectList.updateObjectCost(objectId, objectCost, linkCost, physicsCost, linkPhysicsCost);
+        }
+        else
+        {
+            // TODO*: Give user feedback about the missing data?
+            gObjectList.onObjectCostFetchFailure(objectId);
+        }
+    }
+
+}
+
 void LLViewerObjectList::fetchPhysicsFlags()
 {
 	// issue http request for stale object physics flags
@@ -1232,41 +1120,8 @@ void LLViewerObjectList::fetchPhysicsFlags()
 
 			if (!url.empty())
 			{
-				LLSD id_list;
-				U32 object_index = 0;
-
-				for (
-					std::set<LLUUID>::iterator iter = mStalePhysicsFlags.begin();
-					iter != mStalePhysicsFlags.end();
-					)
-				{
-					// Check to see if a request for this object
-					// has already been made.
-					if ( mPendingPhysicsFlags.find(*iter) ==
-						 mPendingPhysicsFlags.end() )
-					{
-						mPendingPhysicsFlags.insert(*iter);
-						id_list[object_index++] = *iter;
-					}
-
-					mStalePhysicsFlags.erase(iter++);
-					
-					if (object_index >= MAX_CONCURRENT_PHYSICS_REQUESTS)
-					{
-						break;
-					}
-				}
-
-				if ( id_list.size() > 0 )
-				{
-					LLSD post_data = LLSD::emptyMap();
-
-					post_data["object_ids"] = id_list;
-					LLHTTPClient::post(
-						url,
-						post_data,
-						new LLPhysicsFlagsResponder(id_list));
-				}
+                LLCoros::instance().launch("LLViewerObjectList::fetchPhisicsFlagsCoro",
+                    boost::bind(&LLViewerObjectList::fetchPhisicsFlagsCoro, this, url));
 			}
 			else
 			{
@@ -1277,6 +1132,109 @@ void LLViewerObjectList::fetchPhysicsFlags()
 	}
 }
 
+/*static*/
+void LLViewerObjectList::reportPhysicsFlagFailure(LLSD &objectList)
+{
+    // TODO*: No more hard coding
+    for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it)
+    {
+        gObjectList.onPhysicsFlagsFetchFailure(it->asUUID());
+    }
+}
+
+void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD idList;
+    U32 objectIndex = 0;
+
+    for (uuid_set_t::iterator it = mStalePhysicsFlags.begin(); it != mStalePhysicsFlags.end();)
+    {
+        // Check to see if a request for this object
+        // has already been made.
+        if (mPendingPhysicsFlags.find(*it) == mPendingPhysicsFlags.end())
+        {
+            mPendingPhysicsFlags.insert(*it);
+            idList[objectIndex++] = *it;
+        }
+
+        mStalePhysicsFlags.erase(it++);
+
+        if (objectIndex >= MAX_CONCURRENT_PHYSICS_REQUESTS)
+        {
+            break;
+        }
+    }
+
+    if (idList.size() < 1)
+    {
+        LL_INFOS() << "No outstanding object physics flags to request." << LL_ENDL;
+        return;
+    }
+
+    LLSD postData = LLSD::emptyMap();
+
+    postData["object_ids"] = idList;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status || result.has("error"))
+    {
+        if (result.has("error"))
+        {
+            LL_WARNS() << "Application level error when fetching object "
+                << "physics flags.  Message: " << result["error"]["message"].asString()
+                << ", identifier: " << result["error"]["identifier"].asString()
+                << LL_ENDL;
+
+            // TODO*: Adaptively adjust request size if the
+            // service says we've requested too many and retry
+        }
+        reportPhysicsFlagFailure(idList);
+
+        return;
+    }
+
+    // Success, grab the resource cost and linked set costs
+    // for an object if one was returned
+    for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it)
+    {
+        LLUUID objectId = it->asUUID();
+
+        // Check to see if the request contains data for the object
+        if (result.has(it->asString()))
+        {
+            const LLSD& data = result[it->asString()];
+
+            S32 shapeType = data["PhysicsShapeType"].asInteger();
+
+            gObjectList.updatePhysicsShapeType(objectId, shapeType);
+
+            if (data.has("Density"))
+            {
+                F32 density = data["Density"].asReal();
+                F32 friction = data["Friction"].asReal();
+                F32 restitution = data["Restitution"].asReal();
+                F32 gravityMult = data["GravityMultiplier"].asReal();
+
+                gObjectList.updatePhysicsProperties(objectId, density, 
+                    friction, restitution, gravityMult);
+            }
+        }
+        else
+        {
+            // TODO*: Give user feedback about the missing data?
+            gObjectList.onPhysicsFlagsFetchFailure(objectId);
+        }
+    }
+}
 
 void LLViewerObjectList::clearDebugText()
 {
@@ -1563,8 +1521,6 @@ void LLViewerObjectList::updateObjectCost(LLViewerObject* object)
 
 void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost)
 {
-	mPendingObjectCost.erase(object_id);
-
 	LLViewerObject* object = findObject(object_id);
 	if (object)
 	{
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 594317cd9ff2b83829895470fe4b6789b0565b16..94c751acc66b3d40b84626b60099a779d60edc08 100755
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -36,6 +36,8 @@
 
 // project includes
 #include "llviewerobject.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLCamera;
 class LLNetMap;
@@ -203,17 +205,17 @@ class LLViewerObjectList
 
 	vobj_list_t mMapObjects;
 
-	std::set<LLUUID> mDeadObjects;	
+    uuid_set_t   mDeadObjects;
 
 	std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
 
 	//set of objects that need to update their cost
-	std::set<LLUUID> mStaleObjectCost;
-	std::set<LLUUID> mPendingObjectCost;
+    uuid_set_t   mStaleObjectCost;
+    uuid_set_t   mPendingObjectCost;
 
 	//set of objects that need to update their physics flags
-	std::set<LLUUID> mStalePhysicsFlags;
-	std::set<LLUUID> mPendingPhysicsFlags;
+    uuid_set_t   mStalePhysicsFlags;
+    uuid_set_t   mPendingPhysicsFlags;
 
 	std::vector<LLDebugBeacon> mDebugBeacons;
 
@@ -227,6 +229,14 @@ class LLViewerObjectList
 	std::set<LLViewerObject *> mSelectPickList;
 
 	friend class LLViewerObject;
+
+private:
+    static void reportObjectCostFailure(LLSD &objectList);
+    void fetchObjectCostsCoro(std::string url);
+
+    static void reportPhysicsFlagFailure(LLSD &obejectList);
+    void fetchPhisicsFlagsCoro(std::string url);
+
 };
 
 
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 37b249dddd14c2cbdb8ac373b8be136981d3bcde..828271da7a9b4462ce20e2f5a758109107cb8b38 100755
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -43,6 +43,7 @@
 //#include "llfirstuse.h"
 #include "llpluginclassmedia.h"
 #include "llviewertexture.h"
+#include "llcorehttputil.h"
 
 // Static Variables
 
@@ -457,6 +458,7 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
 }
 // Static
 /////////////////////////////////////////////////////////////////////////////////////////
+// *TODO: I can not find any active code where this method is called...
 void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
 {
 	std::string region_url = gAgent.getRegion()->getCapability("ParcelNavigateMedia");
@@ -467,7 +469,9 @@ void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
 		body["agent-id"] = gAgent.getID();
 		body["local-id"] = LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
 		body["url"] = url;
-		LLHTTPClient::post(region_url, body, new LLHTTPClient::Responder);
+
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(region_url, body,
+            "Media Navigation sent to sim.", "Media Navigation failed to send to sim.");
 	}
 	else
 	{
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 2a6b105cab01f09ab0ff56be672e39b2ff1a5ec6..f8c13239a06e1a59936ff41107556d845188196b 100755
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -67,6 +67,7 @@
 #include "roles_constants.h"
 #include "llweb.h"
 #include "llvieweraudio.h"
+#include "llcorehttputil.h"
 
 const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
 
@@ -1286,10 +1287,13 @@ const std::string& LLViewerParcelMgr::getAgentParcelName() const
 
 void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region)
 {
-	if(!parcel) return;
+	if(!parcel) 
+        return;
 
 	LLViewerRegion *region = use_agent_region ? gAgent.getRegion() : LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
-	if (!region) return;
+	if (!region) 
+        return;
+
 	//LL_INFOS() << "found region: " << region->getName() << LL_ENDL;
 
 	LLSD body;
@@ -1302,7 +1306,9 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag
 		parcel->packMessage(body);
 		LL_INFOS() << "Sending parcel properties update via capability to: "
 			<< url << LL_ENDL;
-		LLHTTPClient::post(url, body, new LLHTTPClient::Responder());
+
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
+            "Parcel Properties sent to sim.", "Parcel Properties failed to send to sim.");
 	}
 	else
 	{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 6af3e40f017e9e9bc28ee7499c4dbf789e6c9515..b0280ef3e0b173728c167a5b8cec851918f0b494 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -34,7 +34,6 @@
 #include "llavatarnamecache.h"		// name lookup cap url
 #include "llfloaterreg.h"
 #include "llmath.h"
-#include "llhttpclient.h"
 #include "llregionflags.h"
 #include "llregionhandle.h"
 #include "llsurface.h"
@@ -47,8 +46,6 @@
 #include "llagentcamera.h"
 #include "llavatarrenderinfoaccountant.h"
 #include "llcallingcard.h"
-#include "llcaphttpsender.h"
-#include "llcapabilitylistener.h"
 #include "llcommandhandler.h"
 #include "lldir.h"
 #include "lleventpoll.h"
@@ -78,6 +75,9 @@
 #include "llviewerdisplay.h"
 #include "llviewerwindow.h"
 #include "llprogressview.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llcorehttputil.h"
 
 #ifdef LL_WINDOWS
 	#pragma warning(disable:4355)
@@ -92,7 +92,6 @@
 // We want to allow for seed cap retry, but its not useful after that 60 seconds.
 // Give it 3 chances, each at 18 seconds to give ourselves a few seconds to connect anyways if we give up.
 const S32 MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN = 3;
-const F32 CAP_REQUEST_TIMEOUT = 18;
 // Even though we gave up on login, keep trying for caps after we are logged in:
 const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
 const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
@@ -105,31 +104,62 @@ typedef std::map<std::string, std::string> CapabilityMap;
 
 static void log_capabilities(const CapabilityMap &capmap);
 
-class LLViewerRegionImpl {
+// support for secondlife:///app/region/{REGION} SLapps
+// N.B. this is defined to work exactly like the classic secondlife://{REGION}
+// However, the later syntax cannot support spaces in the region name because
+// spaces (and %20 chars) are illegal in the hostname of an http URL. Some
+// browsers let you get away with this, but some do not (such as Qt's Webkit).
+// Hence we introduced the newer secondlife:///app/region alternative.
+class LLRegionHandler : public LLCommandHandler
+{
+public:
+    // requests will be throttled from a non-trusted browser
+    LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {}
+       
+    bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+    {
+        // make sure that we at least have a region name
+        int num_params = params.size();
+        if (num_params < 1)
+        {
+            return false;
+        }
+           
+        // build a secondlife://{PLACE} SLurl from this SLapp
+        std::string url = "secondlife://";
+        for (int i = 0; i < num_params; i++)
+        {
+            if (i > 0)
+            {
+                url += "/";
+            }
+            url += params[i].asString();
+        }
+           
+        // Process the SLapp as if it was a secondlife://{PLACE} SLurl
+        LLURLDispatcher::dispatch(url, "clicked", web, true);
+        return true;
+    }
+       
+};
+LLRegionHandler gRegionHandler;
+
+
+class LLViewerRegionImpl 
+{
 public:
-	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host)
-		:	mHost(host),
-			mCompositionp(NULL),
-			mEventPoll(NULL),
-			mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS),
-			mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN),
-			mSeedCapAttempts(0),
-			mHttpResponderID(0),
-		mLastCameraUpdate(0),
-		mLastCameraOrigin(),
-		mVOCachePartition(NULL),
-		mLandp(NULL),
-		    // I'd prefer to set the LLCapabilityListener name to match the region
-		    // name -- it's disappointing that's not available at construction time.
-		    // We could instead store an LLCapabilityListener*, making
-		    // setRegionNameAndZone() replace the instance. Would that pose
-		    // consistency problems? Can we even request a capability before calling
-		    // setRegionNameAndZone()?
-		    // For testability -- the new Michael Feathers paradigm --
-		    // LLCapabilityListener binds all the globals it expects to need at
-		    // construction time.
-		    mCapabilityListener(host.getString(), gMessageSystem, *region,
-		                        gAgent.getID(), gAgent.getSessionID())
+	LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host):   
+        mHost(host),
+        mCompositionp(NULL),
+        mEventPoll(NULL),
+        mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS),
+        mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN),
+        mSeedCapAttempts(0),
+        mHttpResponderID(0),
+        mLastCameraUpdate(0),
+        mLastCameraOrigin(),
+        mVOCachePartition(NULL),
+        mLandp(NULL)
 	{}
 
 	void buildCapabilityNames(LLSD& capabilityNames);
@@ -181,220 +211,292 @@ class LLViewerRegionImpl {
 
 	S32 mHttpResponderID;
 
-	/// Post an event to this LLCapabilityListener to invoke a capability message on
-	/// this LLViewerRegion's server
-	/// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-	LLCapabilityListener mCapabilityListener;
-
 	//spatial partitions for objects in this region
 	std::vector<LLViewerOctreePartition*> mObjectPartition;
 
-	LLVector3 mLastCameraOrigin;
-	U32       mLastCameraUpdate;
-};
-
-// support for secondlife:///app/region/{REGION} SLapps
-// N.B. this is defined to work exactly like the classic secondlife://{REGION}
-// However, the later syntax cannot support spaces in the region name because
-// spaces (and %20 chars) are illegal in the hostname of an http URL. Some
-// browsers let you get away with this, but some do not (such as Qt's Webkit).
-// Hence we introduced the newer secondlife:///app/region alternative.
-class LLRegionHandler : public LLCommandHandler
-{
-public:
-	// requests will be throttled from a non-trusted browser
-	LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {}
-
-	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
-	{
-		// make sure that we at least have a region name
-		int num_params = params.size();
-		if (num_params < 1)
-		{
-			return false;
-		}
-
-		// build a secondlife://{PLACE} SLurl from this SLapp
-		std::string url = "secondlife://";
-		for (int i = 0; i < num_params; i++)
-		{
-			if (i > 0)
-			{
-				url += "/";
-			}
-			url += params[i].asString();
-		}
+	LLVector3   mLastCameraOrigin;
+	U32         mLastCameraUpdate;
 
-		// Process the SLapp as if it was a secondlife://{PLACE} SLurl
-		LLURLDispatcher::dispatch(url, "clicked", web, true);
-		return true;
-	}
+    void        requestBaseCapabilitiesCoro(U64 regionHandle);
+    void        requestBaseCapabilitiesCompleteCoro(U64 regionHandle);
+    void        requestSimulatorFeatureCoro(std::string url, U64 regionHandle);
 };
-LLRegionHandler gRegionHandler;
 
-class BaseCapabilitiesComplete : public LLHTTPClient::Responder
+void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
 {
-	LOG_CLASS(BaseCapabilitiesComplete);
-public:
-	BaseCapabilitiesComplete(U64 region_handle, S32 id)
-		: mRegionHandle(region_handle), mID(id)
-	{ }
-	virtual ~BaseCapabilitiesComplete()
-	{ }
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t 
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-	static BaseCapabilitiesComplete* build( U64 region_handle, S32 id )
-	{
-		return new BaseCapabilitiesComplete(region_handle, id);
-	}
+    LLSD result;
+    LLViewerRegion *regionp = NULL;
 
-private:
-	/* virtual */void httpFailure()
-	{
-		LL_WARNS("AppInit", "Capabilities") << dumpResponse() << LL_ENDL;
-		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if (regionp)
-		{
-			regionp->failedSeedCapability();
-		}
-	}
+    // This loop is used for retrying a capabilities request.
+    do
+    {
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
+            return; // this error condition is not recoverable.
+        }
+
+        std::string url = regionp->getCapability("Seed");
+        if (url.empty())
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL;
+            return; // this error condition is not recoverable.
+        }
+
+        // After a few attempts, continue login.  But keep trying to get the caps:
+        if (mSeedCapAttempts >= mSeedCapMaxAttemptsBeforeLogin &&
+            STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
+        {
+            LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED);
+        }
+
+        if (mSeedCapAttempts > mSeedCapMaxAttempts)
+        {
+            // *TODO: Give a user pop-up about this error?
+            LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL;
+            return;  // this error condition is not recoverable.
+        }
+
+        S32 id = ++mHttpResponderID;
+        ++mSeedCapAttempts;
+
+        LLSD capabilityNames = LLSD::emptyArray();
+        buildCapabilityNames(capabilityNames);
+
+        LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url 
+            << " (attempt #" << mSeedCapAttempts << ")" << LL_ENDL;
+
+        regionp = NULL;
+        result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
+
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
+            return; // this error condition is not recoverable.
+        }
+
+        if (id != mHttpResponderID) // region is no longer referring to this request
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Received results for a stale capabilities request!" << LL_ENDL;
+            // setup for retry.
+            continue;
+        }
+
+        LLSD httpResults = result["http_result"];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+        if (!status)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL;
+            // setup for retry.
+            continue;
+        }
+
+        // remove the http_result from the llsd
+        result.erase("http_result");
+
+        LLSD::map_const_iterator iter;
+        for (iter = result.beginMap(); iter != result.endMap(); ++iter)
+        {
+            regionp->setCapability(iter->first, iter->second);
+
+            LL_DEBUGS("AppInit", "Capabilities")
+                << "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL;
+        }
 
-	/* virtual */ void httpSuccess()
-	{
-		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if(!regionp) //region was removed
-		{
-			LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
-			return ;
-		}
-		if( mID != regionp->getHttpResponderID() ) // region is no longer referring to this responder
-		{
-			LL_WARNS("AppInit", "Capabilities") << "Received results for a stale http responder!" << LL_ENDL;
-			regionp->failedSeedCapability();
-			return ;
-		}
+#if 0
+        log_capabilities(mCapabilities);
+#endif
 
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		LLSD::map_const_iterator iter;
-		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-		{
-			regionp->setCapability(iter->first, iter->second);
+        regionp->setCapabilitiesReceived(true);
 
-			LL_DEBUGS("AppInit", "Capabilities")
-				<< "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL;
+        if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
+        {
+            LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED);
+        }
 
-			/* HACK we're waiting for the ServerReleaseNotes */
-			if (iter->first == "ServerReleaseNotes" && regionp->getReleaseNotesRequested())
-			{
-				regionp->showReleaseNotes();
-			}
-		}
+        break;
+    } 
+    while (true);
 
-		regionp->setCapabilitiesReceived(true);
+    if (regionp && regionp->isCapabilityAvailable("ServerReleaseNotes") &&
+            regionp->getReleaseNotesRequested())
+    {   // *HACK: we're waiting for the ServerReleaseNotes
+        regionp->showReleaseNotes();
+    }
 
-		if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
-		{
-			LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
-		}
-	}
+}
 
-private:
-	U64 mRegionHandle;
-	S32 mID;
-};
 
-class BaseCapabilitiesCompleteTracker :  public LLHTTPClient::Responder
+void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
 {
-	LOG_CLASS(BaseCapabilitiesCompleteTracker);
-public:
-	BaseCapabilitiesCompleteTracker( U64 region_handle)
-	: mRegionHandle(region_handle)
-	{ }
-	
-	virtual ~BaseCapabilitiesCompleteTracker()
-	{ }
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
 
-	static BaseCapabilitiesCompleteTracker* build( U64 region_handle )
-	{
-		return new BaseCapabilitiesCompleteTracker( region_handle );
-	}
+    LLSD result;
+    LLViewerRegion *regionp = NULL;
 
-private:
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
+    // This loop is used for retrying a capabilities request.
+    do
+    {
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
+            break; // this error condition is not recoverable.
+        }
+
+        std::string url = regionp->getCapabilityDebug("Seed");
+        if (url.empty())
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url!" << LL_ENDL;
+            break; // this error condition is not recoverable.
+        }
+
+        LLSD capabilityNames = LLSD::emptyArray();
+        buildCapabilityNames(capabilityNames);
+
+        LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << LL_ENDL;
+
+        regionp = NULL;
+        result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
+
+        LLSD httpResults = result["http_result"];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+        if (!status)
+        {
+            LL_WARNS("AppInit", "Capabilities") << "HttpStatus error " << LL_ENDL;
+            break;  // no retry
+        }
+
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
+            break; // this error condition is not recoverable.
+        }
+
+        // remove the http_result from the llsd
+        result.erase("http_result");
+
+        LLSD::map_const_iterator iter;
+        for (iter = result.beginMap(); iter != result.endMap(); ++iter)
+        {
+            regionp->setCapabilityDebug(iter->first, iter->second);
+            //LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<<iter->first<<" "<< iter->second<<LL_ENDL;
+        }
 
-	/* virtual */ void httpSuccess()
-	{
-		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if( !regionp ) 
-		{
-			LL_WARNS("AppInit", "Capabilities") << "Received results for region that no longer exists!" << LL_ENDL;
-			return ;
-		}
+#if 0
+        log_capabilities(mCapabilities);
+#endif
 
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		LLSD::map_const_iterator iter;
-		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-		{
-			regionp->setCapabilityDebug(iter->first, iter->second);	
-			//LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<<iter->first<<" "<< iter->second<<LL_ENDL;
-		}
-		
-		if ( regionp->getRegionImpl()->mCapabilities.size() != regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() )
-		{
-			LL_WARNS("AppInit", "Capabilities") 
-				<< "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
-				<< "mCapabilities == " << regionp->getRegionImpl()->mCapabilities.size()
-				<< " mSecondCapabilitiesTracker == " << regionp->getRegionImpl()->mSecondCapabilitiesTracker.size()
-				<< LL_ENDL;
+        if (mCapabilities.size() != mSecondCapabilitiesTracker.size())
+        {
+            LL_WARNS("AppInit", "Capabilities")
+                << "Sim sent duplicate base caps that differ in size from what we initially received - most likely content. "
+                << "mCapabilities == " << mCapabilities.size()
+                << " mSecondCapabilitiesTracker == " << mSecondCapabilitiesTracker.size()
+                << LL_ENDL;
 #ifdef DEBUG_CAPS_GRANTS
-			LL_WARNS("AppInit", "Capabilities")
-				<< "Initial Base capabilities: " << LL_ENDL;
+            LL_WARNS("AppInit", "Capabilities")
+                << "Initial Base capabilities: " << LL_ENDL;
 
-			log_capabilities(regionp->getRegionImpl()->mCapabilities);
+            log_capabilities(mCapabilities);
 
-			LL_WARNS("AppInit", "Capabilities")
-							<< "Latest base capabilities: " << LL_ENDL;
+            LL_WARNS("AppInit", "Capabilities")
+                << "Latest base capabilities: " << LL_ENDL;
 
-			log_capabilities(regionp->getRegionImpl()->mSecondCapabilitiesTracker);
+            log_capabilities(mSecondCapabilitiesTracker);
 
 #endif
 
-			if (regionp->getRegionImpl()->mSecondCapabilitiesTracker.size() > regionp->getRegionImpl()->mCapabilities.size() )
-			{
-				// *HACK Since we were granted more base capabilities in this grant request than the initial, replace
-				// the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a
-				// sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the
-				// inventory api capability grants.
-
-				// Need to clear a std::map before copying into it because old keys take precedence.
-				regionp->getRegionImplNC()->mCapabilities.clear();
-				regionp->getRegionImplNC()->mCapabilities = regionp->getRegionImpl()->mSecondCapabilitiesTracker;
-			}
-		}
-		else
-		{
-			LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
-		}
-		regionp->getRegionImplNC()->mSecondCapabilitiesTracker.clear();
-	}
+            if (mSecondCapabilitiesTracker.size() > mCapabilities.size())
+            {
+                // *HACK Since we were granted more base capabilities in this grant request than the initial, replace
+                // the old with the new. This shouldn't happen i.e. we should always get the same capabilities from a
+                // sim. The simulator fix from SH-3895 should prevent it from happening, at least in the case of the
+                // inventory api capability grants.
 
+                // Need to clear a std::map before copying into it because old keys take precedence.
+                mCapabilities.clear();
+                mCapabilities = mSecondCapabilitiesTracker;
+            }
+        }
+        else
+        {
+            LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL;
+        }
+        mSecondCapabilitiesTracker.clear();
+    } 
+    while (false);
 
-private:
-	U64 mRegionHandle;
-};
 
+}
+
+void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 regionHandle)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLViewerRegion *regionp = NULL;
+    S32 attemptNumber = 0;
+    // This loop is used for retrying a capabilities request.
+    do
+    {
+        ++attemptNumber;
+
+        if (attemptNumber > MAX_CAP_REQUEST_ATTEMPTS)
+        {
+            LL_WARNS("AppInit", "SimulatorFeatures") << "Retries count exceeded attempting to get Simulator feature from " 
+                << url << LL_ENDL;
+            break;
+        }
+
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to request Sim Feature for region that no longer exists!" << LL_ENDL;
+            break; // this error condition is not recoverable.
+        }
+
+        regionp = NULL;
+        LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+        LLSD httpResults = result["http_result"];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+        if (!status)
+        {
+            LL_WARNS("AppInit", "SimulatorFeatures") << "HttpStatus error retrying" << LL_ENDL;
+            continue;  
+        }
+
+        // remove the http_result from the llsd
+        result.erase("http_result");
+
+        regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+        if (!regionp) //region was removed
+        {
+            LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to set Sim Feature for region that no longer exists!" << LL_ENDL;
+            break; // this error condition is not recoverable.
+        }
+
+        regionp->setSimulatorFeatures(result);
+
+        break;
+    }
+    while (true);
+
+}
 
 LLViewerRegion::LLViewerRegion(const U64 &handle,
 							   const LLHost &host,
@@ -515,8 +617,9 @@ LLViewerRegion::~LLViewerRegion()
 	delete mParcelOverlay;
 	delete mImpl->mLandp;
 	delete mImpl->mEventPoll;
+#if 0
 	LLHTTPSender::clearSender(mImpl->mHost);
-	
+#endif	
 	std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
 
 	saveObjectCache();
@@ -525,11 +628,6 @@ LLViewerRegion::~LLViewerRegion()
 	mImpl = NULL;
 }
 
-LLEventPump& LLViewerRegion::getCapAPI() const
-{
-	return mImpl->mCapabilityListener.getCapAPI();
-}
-
 /*virtual*/ 
 const LLHost&	LLViewerRegion::getHost() const				
 { 
@@ -2730,7 +2828,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("FetchInventory2");
 	capabilityNames.append("FetchInventoryDescendents2");
 	capabilityNames.append("IncrementCOFVersion");
-	AISCommand::getCapabilityNames(capabilityNames);
+	AISAPI::getCapNames(capabilityNames);
 
 	capabilityNames.append("GetDisplayNames");
 	capabilityNames.append("GetExperiences");
@@ -2810,15 +2908,14 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	if (getCapability("Seed") == url)
     {	
 		setCapabilityDebug("Seed", url);
-		LL_DEBUGS("CrossingCaps") <<  "Received duplicate seed capability, posting to seed " <<
+		LL_WARNS("CrossingCaps") <<  "Received duplicate seed capability, posting to seed " <<
 				url	<< LL_ENDL;
 
 		//Instead of just returning we build up a second set of seed caps and compare them 
 		//to the "original" seed cap received and determine why there is problem!
-		LLSD capabilityNames = LLSD::emptyArray();
-		mImpl->buildCapabilityNames( capabilityNames );
-		LLHTTPClient::post( url, capabilityNames, BaseCapabilitiesCompleteTracker::build(getHandle() ),
-							LLSD(), CAP_REQUEST_TIMEOUT );
+        std::string coroname =
+            LLCoros::instance().launch("LLEnvironmentRequest::requestBaseCapabilitiesCompleteCoro",
+            boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, mImpl, getHandle()));
 		return;
     }
 	
@@ -2828,15 +2925,11 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	mImpl->mCapabilities.clear();
 	setCapability("Seed", url);
 
-	LLSD capabilityNames = LLSD::emptyArray();
-	mImpl->buildCapabilityNames(capabilityNames);
-
-	LL_INFOS() << "posting to seed " << url << LL_ENDL;
+    std::string coroname =
+        LLCoros::instance().launch("LLViewerRegionImpl::requestBaseCapabilitiesCoro",
+        boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCoro, mImpl, getHandle()));
 
-	S32 id = ++mImpl->mHttpResponderID;
-	LLHTTPClient::post(url, capabilityNames, 
-						BaseCapabilitiesComplete::build(getHandle(), id),
-						LLSD(), CAP_REQUEST_TIMEOUT);
+    LL_INFOS("AppInit", "Capabilities") << "Launching " << coroname << " requesting seed capabilities from " << url << LL_ENDL;
 }
 
 S32 LLViewerRegion::getNumSeedCapRetries()
@@ -2844,94 +2937,6 @@ S32 LLViewerRegion::getNumSeedCapRetries()
 	return mImpl->mSeedCapAttempts;
 }
 
-void LLViewerRegion::failedSeedCapability()
-{
-	// Should we retry asking for caps?
-	mImpl->mSeedCapAttempts++;
-	std::string url = getCapability("Seed");
-	if ( url.empty() )
-	{
-		LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities, and can not determine url for retries!" << LL_ENDL;
-		return;
-	}
-	// After a few attempts, continue login.  We will keep trying once in-world:
-	if ( mImpl->mSeedCapAttempts >= mImpl->mSeedCapMaxAttemptsBeforeLogin &&
-		 STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState() )
-	{
-		LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
-	}
-
-	if ( mImpl->mSeedCapAttempts < mImpl->mSeedCapMaxAttempts)
-	{
-		LLSD capabilityNames = LLSD::emptyArray();
-		mImpl->buildCapabilityNames(capabilityNames);
-
-		LL_INFOS() << "posting to seed " << url << " (retry " 
-				<< mImpl->mSeedCapAttempts << ")" << LL_ENDL;
-
-		S32 id = ++mImpl->mHttpResponderID;
-		LLHTTPClient::post(url, capabilityNames, 
-						BaseCapabilitiesComplete::build(getHandle(), id),
-						LLSD(), CAP_REQUEST_TIMEOUT);
-	}
-	else
-	{
-		// *TODO: Give a user pop-up about this error?
-		LL_WARNS("AppInit", "Capabilities") << "Failed to get seed capabilities from '" << url << "' after " << mImpl->mSeedCapAttempts << " attempts.  Giving up!" << LL_ENDL;
-	}
-}
-
-class SimulatorFeaturesReceived : public LLHTTPClient::Responder
-{
-	LOG_CLASS(SimulatorFeaturesReceived);
-public:
-	SimulatorFeaturesReceived(const std::string& retry_url, U64 region_handle, 
-							  S32 attempt = 0, S32 max_attempts = MAX_CAP_REQUEST_ATTEMPTS)
-		: mRetryURL(retry_url), mRegionHandle(region_handle), mAttempt(attempt), mMaxAttempts(max_attempts)
-	{ }
-
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS("AppInit", "SimulatorFeatures") << dumpResponse() << LL_ENDL;
-		retry();
-	}
-
-	/* virtual */ void httpSuccess()
-	{
-		LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
-		if(!regionp) //region is removed or responder is not created.
-		{
-			LL_WARNS("AppInit", "SimulatorFeatures") 
-				<< "Received results for region that no longer exists!" << LL_ENDL;
-			return ;
-		}
-
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		regionp->setSimulatorFeatures(content);
-	}
-
-	void retry()
-	{
-		if (mAttempt < mMaxAttempts)
-		{
-			mAttempt++;
-			LL_WARNS("AppInit", "SimulatorFeatures") << "Re-trying '" << mRetryURL << "'.  Retry #" << mAttempt << LL_ENDL;
-			LLHTTPClient::get(mRetryURL, new SimulatorFeaturesReceived(*this), LLSD(), CAP_REQUEST_TIMEOUT);
-		}
-	}
-
-	std::string mRetryURL;
-	U64 mRegionHandle;
-	S32 mAttempt;
-	S32 mMaxAttempts;
-};
-
-
 void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
 {
 	if(name == "EventQueueGet")
@@ -2942,12 +2947,16 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
 	}
 	else if(name == "UntrustedSimulatorMessage")
 	{
-		LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
+        mImpl->mHost.setUntrustedSimulatorCap(url);
 	}
 	else if (name == "SimulatorFeatures")
 	{
 		// kick off a request for simulator features
-		LLHTTPClient::get(url, new SimulatorFeaturesReceived(url, getHandle()), LLSD(), CAP_REQUEST_TIMEOUT);
+        std::string coroname =
+            LLCoros::instance().launch("LLViewerRegionImpl::requestSimulatorFeatureCoro",
+            boost::bind(&LLViewerRegionImpl::requestSimulatorFeatureCoro, mImpl, url, getHandle()));
+
+        LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << LL_ENDL;
 	}
 	else
 	{
@@ -2970,9 +2979,20 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri
 			mHttpUrl = url ;
 		}
 	}
+}
 
+std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const
+{
+    CapabilityMap::const_iterator iter = mImpl->mSecondCapabilitiesTracker.find(name);
+    if (iter == mImpl->mSecondCapabilitiesTracker.end())
+    {
+        return "";
+    }
+
+    return iter->second;
 }
 
+
 bool LLViewerRegion::isSpecialCapabilityName(const std::string &name)
 {
 	return name == "EventQueueGet" || name == "UntrustedSimulatorMessage";
@@ -3025,7 +3045,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received)
 	{
 		mCapabilitiesReceivedSignal(getRegionID());
 
-		LLFloaterPermsDefault::sendInitialPerms();
+		//LLFloaterPermsDefault::sendInitialPerms();
 
 		// This is a single-shot signal. Forget callbacks to save resources.
 		mCapabilitiesReceivedSignal.disconnect_all_slots();
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index c14fa5aee805c62bf9322237b428a49de8711a97..8c4966369c35e78bc570dea45272f02b36074496 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -40,7 +40,6 @@
 #include "llweb.h"
 #include "llcapabilityprovider.h"
 #include "m4math.h"					// LLMatrix4
-#include "llhttpclient.h"
 #include "llframetimer.h"
 
 // Surface id's
@@ -62,7 +61,6 @@ class LLVOCache;
 class LLVOCacheEntry;
 class LLSpatialPartition;
 class LLEventPump;
-class LLCapabilityListener;
 class LLDataPacker;
 class LLDataPackerBinaryBuffer;
 class LLHost;
@@ -253,13 +251,14 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	// Get/set named capability URLs for this region.
 	void setSeedCapability(const std::string& url);
-	void failedSeedCapability();
 	S32 getNumSeedCapRetries();
 	void setCapability(const std::string& name, const std::string& url);
 	void setCapabilityDebug(const std::string& name, const std::string& url);
 	bool isCapabilityAvailable(const std::string& name) const;
 	// implements LLCapabilityProvider
     virtual std::string getCapability(const std::string& name) const;
+    std::string getCapabilityDebug(const std::string& name) const;
+
 
 	// has region received its final (not seed) capability list?
 	bool capabilitiesReceived() const;
@@ -269,10 +268,6 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	static bool isSpecialCapabilityName(const std::string &name);
 	void logActiveCapabilities() const;
 
-    /// Get LLEventPump on which we listen for capability requests
-    /// (https://wiki.lindenlab.com/wiki/Viewer:Messaging/Messaging_Notes#Capabilities)
-    LLEventPump& getCapAPI() const;
-
     /// implements LLCapabilityProvider
 	/*virtual*/ const LLHost& getHost() const;
 	const U64 		&getHandle() const 			{ return mHandle; }
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index f60829e9e8def1169f7e95c9b47219c7a9383ce5..2c3067cd3ac2bff604dcf3de13f5b43f7a8c10fc 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -60,6 +60,7 @@
 #include "llfeaturemanager.h"
 #include "llviewernetwork.h"
 #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived
+#include "llcorehttputil.h"
 
 namespace LLStatViewer
 {
@@ -410,24 +411,6 @@ void update_statistics()
 	}
 }
 
-class ViewerStatsResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(ViewerStatsResponder);
-public:
-	ViewerStatsResponder() { }
-
-private:
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
-
-	/* virtual */ void httpSuccess()
-	{
-		LL_INFOS() << "OK" << LL_ENDL;
-	}
-};
-
 /*
  * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.
  *
@@ -618,8 +601,8 @@ void send_stats()
 	body["MinimalSkin"] = false;
 	
 	LLViewerStats::getInstance()->addToMessage(body);
-	LLHTTPClient::post(url, body, new ViewerStatsResponder());
-
+    LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
+        "Statistics posted to sim", "Failed to post statistics to sim");
 	LLViewerStats::instance().getRecording().resume();
 }
 
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index aed7e94945305c17e151dc71f480c64105862b56..e496cb9f786816b6b7559ecba2ca032e26b4e188 100755
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -266,7 +266,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 protected:
 	/*virtual*/ ~LLViewerFetchedTexture();
 public:
-	LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
+	LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE);
 	LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps);
 	LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);
 
@@ -498,7 +498,7 @@ class LLViewerFetchedTexture : public LLViewerTexture
 	S32 mCachedRawDiscardLevel;
 	BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.	
 
-	LLHost mTargetHost;	// if LLHost::invalid, just request from agent's simulator
+	LLHost mTargetHost;	// if invalid, just request from agent's simulator
 
 	// Timers
 	LLFrameTimer mLastPacketTimer;		// Time since last packet.
@@ -528,7 +528,7 @@ class LLViewerLODTexture : public LLViewerFetchedTexture
 	/*virtual*/ ~LLViewerLODTexture(){}
 
 public:
-	LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE);
+	LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE);
 	LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE);
 
 	/*virtual*/ S8 getType() const;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 926c40307b3d8c659fb52c91e368dbf2a9de2a82..2fbd9f0acbb21f9b4a0d49ca48def713a5ab1969 100755
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -236,7 +236,7 @@ void LLViewerTextureList::shutdown()
 		if (!image->hasGLTexture() ||
 			!image->getUseDiscard() ||
 			image->needsAux() ||
-			image->getTargetHost() != LLHost::invalid ||
+			!image->getTargetHost().isInvalid() ||
 			!image->getUrl().empty()
 			)
 		{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f7534487701d8c773d37986860b94686ecc6b5d5..db949437a721fb403f9a8060efe17833e4bc34f7 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8095,7 +8095,7 @@ LLHost LLVOAvatar::getObjectHost() const
 	}
 	else
 	{
-		return LLHost::invalid;
+		return LLHost();
 	}
 }
 
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index c1ca0aed69cd3ea754a85fa626726179b0a08901..e7dee1438743a006cc9ec5568bdb745fbcc23251 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -65,6 +65,7 @@
 #include "llsdutil.h"
 #include "llstartup.h"
 #include "llsdserialize.h"
+#include "llcorehttputil.h"
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -106,6 +107,9 @@ void selfClearPhases()
 
 using namespace LLAvatarAppearanceDefines;
 
+
+LLSD summarize_by_buckets(std::vector<LLSD> in_records, std::vector<std::string> by_fields, std::string val_field);
+
 /*********************************************************************************
  **                                                                             **
  ** Begin private LLVOAvatarSelf Support classes
@@ -128,25 +132,6 @@ struct LocalTextureData
 	LLTextureEntry *mTexEntry;
 };
 
-// TODO - this class doesn't really do anything, could just use a base
-// class responder if nothing else gets added.
-class LLHoverHeightResponder: public LLHTTPClient::Responder
-{
-public:
-	LLHoverHeightResponder(): LLHTTPClient::Responder() {}
-
-private:
-	void httpFailure()
-	{
-		LL_WARNS() << dumpResponse() << LL_ENDL;
-	}
-
-	void httpSuccess()
-	{
-		LL_INFOS() << dumpResponse() << LL_ENDL;
-	}
-};
-
 //-----------------------------------------------------------------------------
 // Callback data
 //-----------------------------------------------------------------------------
@@ -181,7 +166,9 @@ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id,
 	mRegionCrossingCount(0),
 	// Value outside legal range, so will always be a mismatch the
 	// first time through.
-	mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f))
+	mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f)),
+    mInitialMetric(true),
+    mMetricSequence(0)
 {
 	mMotionController.mIsSelf = TRUE;
 
@@ -2164,43 +2151,76 @@ const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const
 	return text;
 }
 
-class ViewerAppearanceChangeMetricsResponder: public LLCurl::Responder
-{
-	LOG_CLASS(ViewerAppearanceChangeMetricsResponder);
-public:
-	ViewerAppearanceChangeMetricsResponder( S32 expected_sequence,
-											volatile const S32 & live_sequence,
-											volatile bool & reporting_started):
-		mExpectedSequence(expected_sequence),
-		mLiveSequence(live_sequence),
-		mReportingStarted(reporting_started)
-	{
-	}
-
-private:
-	/* virtual */ void httpSuccess()
-	{
-		LL_DEBUGS("Avatar") << "OK" << LL_ENDL;
-
-		gPendingMetricsUploads--;
-		if (mLiveSequence == mExpectedSequence)
-		{
-			mReportingStarted = true;
-		}
-	}
-
-	/* virtual */ void httpFailure()
-	{
-		// if we add retry, this should be removed from the httpFailure case
-		LL_WARNS("Avatar") << dumpResponse() << LL_ENDL;
-		gPendingMetricsUploads--;
-	}
-
-private:
-	S32 mExpectedSequence;
-	volatile const S32 & mLiveSequence;
-	volatile bool & mReportingStarted;
-};
+void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("appearanceChangeMetrics", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+    S32 currentSequence = mMetricSequence;
+    if (S32_MAX == ++mMetricSequence)
+        mMetricSequence = 0;
+
+    LLSD msg;
+    msg["message"] = "ViewerAppearanceChangeMetrics";
+    msg["session_id"] = gAgentSessionID;
+    msg["agent_id"] = gAgentID;
+    msg["sequence"] = currentSequence;
+    msg["initial"] = mInitialMetric;
+    msg["break"] = false;
+    msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32();
+
+    // Status of our own rezzing.
+    msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
+
+    // Status of all nearby avs including ourself.
+    msg["nearby"] = LLSD::emptyArray();
+    std::vector<S32> rez_counts;
+    LLVOAvatar::getNearbyRezzedStats(rez_counts);
+    for (S32 rez_stat = 0; rez_stat < rez_counts.size(); ++rez_stat)
+    {
+        std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat);
+        msg["nearby"][rez_status_name] = rez_counts[rez_stat];
+    }
+
+    //	std::vector<std::string> bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake");
+    std::vector<std::string> by_fields;
+    by_fields.push_back("timer_name");
+    by_fields.push_back("completed");
+    by_fields.push_back("grid_x");
+    by_fields.push_back("grid_y");
+    by_fields.push_back("is_using_server_bakes");
+    by_fields.push_back("is_self");
+    by_fields.push_back("central_bake_version");
+    LLSD summary = summarize_by_buckets(mPendingTimerRecords, by_fields, std::string("elapsed"));
+    msg["timers"] = summary;
+
+    mPendingTimerRecords.clear();
+
+    LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL;
+
+    gPendingMetricsUploads++;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, msg);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    gPendingMetricsUploads--;
+
+    if (!status)
+    {
+        LL_WARNS("Avatar") << "Unable to upload statistics" << LL_ENDL;
+        return;
+    }
+    else
+    {
+        LL_INFOS("Avatar") << "Statistics upload OK" << LL_ENDL;
+        mInitialMetric = false;
+    }
+}
 
 bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send)
 {
@@ -2278,51 +2298,7 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records,
 
 void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 {
-	static volatile bool reporting_started(false);
-	static volatile S32 report_sequence(0);
-
-	LLSD msg;
-	msg["message"] = "ViewerAppearanceChangeMetrics";
-	msg["session_id"] = gAgentSessionID;
-	msg["agent_id"] = gAgentID;
-	msg["sequence"] = report_sequence;
-	msg["initial"] = !reporting_started;
-	msg["break"] = false;
-	msg["duration"] = mTimeSinceLastRezMessage.getElapsedTimeF32();
-
-	// Status of our own rezzing.
-	msg["rez_status"] = LLVOAvatar::rezStatusToString(getRezzedStatus());
-
-	// Status of all nearby avs including ourself.
-	msg["nearby"] = LLSD::emptyArray();
-	std::vector<S32> rez_counts;
-	LLVOAvatar::getNearbyRezzedStats(rez_counts);
-	for (S32 rez_stat=0; rez_stat < rez_counts.size(); ++rez_stat)
-	{
-		std::string rez_status_name = LLVOAvatar::rezStatusToString(rez_stat);
-		msg["nearby"][rez_status_name] = rez_counts[rez_stat];
-	}
-
-	//	std::vector<std::string> bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake");
-	std::vector<std::string> by_fields;
-	by_fields.push_back("timer_name");
-	by_fields.push_back("completed");
-	by_fields.push_back("grid_x");
-	by_fields.push_back("grid_y");
-	by_fields.push_back("is_using_server_bakes");
-	by_fields.push_back("is_self");
-	by_fields.push_back("central_bake_version");
-	LLSD summary = summarize_by_buckets(mPendingTimerRecords, by_fields, std::string("elapsed"));
-	msg["timers"] = summary;
-
-	mPendingTimerRecords.clear();
-
-	// Update sequence number
-	if (S32_MAX == ++report_sequence)
-		report_sequence = 0;
-
-	LL_DEBUGS("Avatar") << avString() << "message: " << ll_pretty_print_sd(msg) << LL_ENDL;
-	std::string	caps_url;
+    std::string	caps_url;
 	if (getRegion())
 	{
 		// runway - change here to activate.
@@ -2330,13 +2306,9 @@ void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics()
 	}
 	if (!caps_url.empty())
 	{
-		gPendingMetricsUploads++;
-		LLCurlRequest::headers_t headers;
-		LLHTTPClient::post(caps_url,
-						   msg,
-						   new ViewerAppearanceChangeMetricsResponder(report_sequence,
-																	  report_sequence,
-																	  reporting_started));
+
+        LLCoros::instance().launch("LLVOAvatarSelf::appearanceChangeMetricsCoro",
+            boost::bind(&LLVOAvatarSelf::appearanceChangeMetricsCoro, this, caps_url));
 		mTimeSinceLastRezMessage.reset();
 	}
 }
@@ -2759,8 +2731,12 @@ void LLVOAvatarSelf::sendHoverHeight() const
 		update["hover_height"] = hover_offset[2];
 
 		LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL;
-		LLHTTPClient::post(url, update, new LLHoverHeightResponder);
 
+        // *TODO: - this class doesn't really do anything, could just use a base
+        // class responder if nothing else gets added. 
+        // (comment from removed Responder)
+        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, update, 
+            "Hover hight sent to sim", "Hover hight not sent to sim");
 		mLastHoverOffsetSent = hover_offset;
 	}
 }
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 257a760eeb2bdeb5ae2369f0f4639d0ccf43439e..cdd82a8a4462179090c962002e31f556ab8ba559 100755
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -31,6 +31,8 @@
 #include "llviewertexture.h"
 #include "llvoavatar.h"
 #include <map>
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 struct LocalTextureData;
 class LLInventoryCallback;
@@ -394,6 +396,9 @@ class LLVOAvatarSelf :
 	F32 					mDebugBakedTextureTimes[LLAvatarAppearanceDefines::BAKED_NUM_INDICES][2]; // time to start upload and finish upload of each baked texture
 	void					debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
 
+    void                    appearanceChangeMetricsCoro(std::string url);
+    bool                    mInitialMetric;
+    S32                     mMetricSequence;
 /**                    Diagnostics
  **                                                                            **
  *******************************************************************************/
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 426ca332e42ddaa24001e388717e7570a7c8fd42..3abb716593f36c028c170c3d6bf41fa79285f424 100755
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -28,7 +28,6 @@
 
 #include "llagent.h"
 #include "llfloaterreg.h"
-#include "llhttpclient.h"
 #include "llimview.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
@@ -37,7 +36,7 @@
 #include "llviewercontrol.h"
 #include "llviewerregion.h"
 #include "llvoicechannel.h"
-
+#include "llcorehttputil.h"
 
 LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
 LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
@@ -52,71 +51,6 @@ BOOL LLVoiceChannel::sSuspended = FALSE;
 //
 const U32 DEFAULT_RETRIES_COUNT = 3;
 
-
-class LLVoiceCallCapResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLVoiceCallCapResponder);
-public:
-	LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
-
-protected:
-	// called with bad status codes
-	virtual void httpFailure();
-	virtual void httpSuccess();
-
-private:
-	LLUUID mSessionID;
-};
-
-
-void LLVoiceCallCapResponder::httpFailure()
-{
-	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if ( channelp )
-	{
-		if ( HTTP_FORBIDDEN == getStatus() )
-		{
-			//403 == no ability
-			LLNotificationsUtil::add(
-				"VoiceNotAllowed",
-				channelp->getNotifyArgs());
-		}
-		else
-		{
-			LLNotificationsUtil::add(
-				"VoiceCallGenericError",
-				channelp->getNotifyArgs());
-		}
-		channelp->deactivate();
-	}
-}
-
-void LLVoiceCallCapResponder::httpSuccess()
-{
-	LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
-	if (channelp)
-	{
-		//*TODO: DEBUG SPAM
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		LLSD::map_const_iterator iter;
-		for(iter = content.beginMap(); iter != content.endMap(); ++iter)
-		{
-			LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got " 
-				<< iter->first << LL_ENDL;
-		}
-
-		channelp->setChannelInfo(
-			content["voice_credentials"]["channel_uri"].asString(),
-			content["voice_credentials"]["channel_credentials"].asString());
-	}
-}
-
 //
 // LLVoiceChannel
 //
@@ -545,12 +479,9 @@ void LLVoiceChannelGroup::getChannelInfo()
 	if (region)
 	{
 		std::string url = region->getCapability("ChatSessionRequest");
-		LLSD data;
-		data["method"] = "call";
-		data["session-id"] = mSessionID;
-		LLHTTPClient::post(url,
-						   data,
-						   new LLVoiceCallCapResponder(mSessionID));
+
+        LLCoros::instance().launch("LLVoiceChannelGroup::voiceCallCapCoro",
+            boost::bind(&LLVoiceChannelGroup::voiceCallCapCoro, this, url));
 	}
 }
 
@@ -673,6 +604,66 @@ void LLVoiceChannelGroup::setState(EState state)
 	}
 }
 
+void LLVoiceChannelGroup::voiceCallCapCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("voiceCallCapCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD postData;
+    postData["method"] = "call";
+    postData["session-id"] = mSessionID;
+
+    LL_INFOS("Voice", "voiceCallCapCoro") << "Generic POST for " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+    if (!channelp)
+    {
+        LL_WARNS("Voice") << "Unable to retrieve channel with Id = " << mSessionID << LL_ENDL;
+        return;
+    }
+
+    if (!status)
+    {
+        if (status == LLCore::HttpStatus(HTTP_FORBIDDEN))
+        {
+            //403 == no ability
+            LLNotificationsUtil::add(
+                "VoiceNotAllowed",
+                channelp->getNotifyArgs());
+        }
+        else
+        {
+            LLNotificationsUtil::add(
+                "VoiceCallGenericError",
+                channelp->getNotifyArgs());
+        }
+        channelp->deactivate();
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+    LLSD::map_const_iterator iter;
+    for (iter = result.beginMap(); iter != result.endMap(); ++iter)
+    {
+        LL_DEBUGS("Voice") << "LLVoiceCallCapResponder::result got "
+            << iter->first << LL_ENDL;
+    }
+
+    channelp->setChannelInfo(
+        result["voice_credentials"]["channel_uri"].asString(),
+        result["voice_credentials"]["channel_credentials"].asString());
+
+}
+
+
 //
 // LLVoiceChannelProximal
 //
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index fed44974fdee8d60548b086ca0327e465f831bc7..ef15b2c79ee2d5c184d7cf6e59df2802168e3ad7 100755
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -29,6 +29,8 @@
 
 #include "llhandle.h"
 #include "llvoiceclient.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 class LLPanel;
 
@@ -157,6 +159,8 @@ class LLVoiceChannelGroup : public LLVoiceChannel
 	virtual void setState(EState state);
 
 private:
+    void voiceCallCapCoro(std::string url);
+
 	U32 mRetries;
 	BOOL mIsRetrying;
 };
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index a6a7a35b03858d2279f13e245e5be2a79c879ada..d14fac5fb8200004cf62c541df8dff4021d50e9b 100755
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -64,6 +64,8 @@
 #include "llviewernetwork.h"
 #include "llnotificationsutil.h"
 
+#include "llcorehttputil.h"
+
 #include "stringize.h"
 
 // for base64 decoding
@@ -122,66 +124,6 @@ static int scale_speaker_volume(float volume)
 	
 }
 
-class LLVivoxVoiceAccountProvisionResponder :
-	public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLVivoxVoiceAccountProvisionResponder);
-public:
-	LLVivoxVoiceAccountProvisionResponder(int retries)
-	{
-		mRetries = retries;
-	}
-
-private:
-	/* virtual */ void httpFailure()
-	{
-		LL_WARNS("Voice") << "ProvisionVoiceAccountRequest returned an error, "
-			<<  ( (mRetries > 0) ? "retrying" : "too many retries (giving up)" )
-			<< " " << dumpResponse() << LL_ENDL;
-
-		if ( mRetries > 0 )
-		{
-			LLVivoxVoiceClient::getInstance()->requestVoiceAccountProvision(mRetries - 1);
-		}
-		else
-		{
-			LLVivoxVoiceClient::getInstance()->giveUp();
-		}
-	}
-
-	/* virtual */ void httpSuccess()
-	{
-		std::string voice_sip_uri_hostname;
-		std::string voice_account_server_uri;
-		
-		LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL;
-		
-		const LLSD& content = getContent();
-		if (!content.isMap())
-		{
-			failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-			return;
-		}
-		if(content.has("voice_sip_uri_hostname"))
-			voice_sip_uri_hostname = content["voice_sip_uri_hostname"].asString();
-		
-		// this key is actually misnamed -- it will be an entire URI, not just a hostname.
-		if(content.has("voice_account_server_name"))
-			voice_account_server_uri = content["voice_account_server_name"].asString();
-		
-		LLVivoxVoiceClient::getInstance()->login(
-			content["username"].asString(),
-			content["password"].asString(),
-			voice_sip_uri_hostname,
-			voice_account_server_uri);
-	}
-
-private:
-	int mRetries;
-};
-
-
-
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 class LLVivoxVoiceClientMuteListObserver : public LLMuteListObserver
@@ -194,59 +136,6 @@ static LLVivoxVoiceClientMuteListObserver mutelist_listener;
 static bool sMuteListListener_listening = false;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
-
-class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLVivoxVoiceClientCapResponder);
-public:
-	LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {};
-
-private:
-	// called with bad status codes
-	/* virtual */ void httpFailure();
-	/* virtual */ void httpSuccess();
-
-	LLVivoxVoiceClient::state mRequestingState;  // state 
-};
-
-void LLVivoxVoiceClientCapResponder::httpFailure()
-{
-	LL_WARNS("Voice") << dumpResponse() << LL_ENDL;
-	LLVivoxVoiceClient::getInstance()->sessionTerminate();
-}
-
-void LLVivoxVoiceClientCapResponder::httpSuccess()
-{
-	LLSD::map_const_iterator iter;
-	
-	LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << dumpResponse() << LL_ENDL;
-
-	std::string uri;
-	std::string credentials;
-	
-	const LLSD& content = getContent();
-	if ( content.has("voice_credentials") )
-	{
-		LLSD voice_credentials = content["voice_credentials"];
-		if ( voice_credentials.has("channel_uri") )
-		{
-			uri = voice_credentials["channel_uri"].asString();
-		}
-		if ( voice_credentials.has("channel_credentials") )
-		{
-			credentials =
-				voice_credentials["channel_credentials"].asString();
-		}
-	}
-	
-	// set the spatial channel.  If no voice credentials or uri are 
-	// available, then we simply drop out of voice spatially.
-	if(LLVivoxVoiceClient::getInstance()->parcelVoiceInfoReceived(mRequestingState))
-	{
-		LLVivoxVoiceClient::getInstance()->setSpatialChannel(uri, credentials);
-	}
-}
-
 static LLProcessPtr sGatewayPtr;
 
 static bool isGatewayRunning()
@@ -556,16 +445,51 @@ void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries)
 		
 		if ( !url.empty() ) 
 		{
-			LLHTTPClient::post(
-							   url,
-							   LLSD(),
-							   new LLVivoxVoiceAccountProvisionResponder(retries));
-		
+            LLCoros::instance().launch("LLVivoxVoiceClient::voiceAccountProvisionCoro",
+                boost::bind(&LLVivoxVoiceClient::voiceAccountProvisionCoro, this, url, retries));
 			setState(stateConnectorStart);		
 		}
 	}
 }
 
+void LLVivoxVoiceClient::voiceAccountProvisionCoro(std::string url, S32 retries)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("voiceAccountProvision", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+    httpOpts->setRetries(retries);
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD(), httpOpts);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("Voice") << "Unable to provision voice account." << LL_ENDL;
+        giveUp();
+        return;
+    }
+
+    std::string voice_sip_uri_hostname;
+    std::string voice_account_server_uri;
+
+    //LL_DEBUGS("Voice") << "ProvisionVoiceAccountRequest response:" << dumpResponse() << LL_ENDL;
+
+    if (result.has("voice_sip_uri_hostname"))
+        voice_sip_uri_hostname = result["voice_sip_uri_hostname"].asString();
+
+    // this key is actually misnamed -- it will be an entire URI, not just a hostname.
+    if (result.has("voice_account_server_name"))
+        voice_account_server_uri = result["voice_account_server_name"].asString();
+
+    login(result["username"].asString(), result["password"].asString(),
+        voice_sip_uri_hostname, voice_account_server_uri);
+}
+
 void LLVivoxVoiceClient::login(
 	const std::string& account_name,
 	const std::string& password,
@@ -4003,14 +3927,60 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo()
 		LLSD data;
 		LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
 		
-		LLHTTPClient::post(
-						url,
-						data,
-						new LLVivoxVoiceClientCapResponder(getState()));
+        LLCoros::instance().launch("LLVivoxVoiceClient::parcelVoiceInfoRequestCoro",
+            boost::bind(&LLVivoxVoiceClient::parcelVoiceInfoRequestCoro, this, url));
 		return true;
 	}
 }
 
+void LLVivoxVoiceClient::parcelVoiceInfoRequestCoro(std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("parcelVoiceInfoRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    state requestingState = getState();
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD());
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("Voice") << "No voice on parcel" << LL_ENDL;
+        sessionTerminate();
+        return;
+    }
+
+    std::string uri;
+    std::string credentials;
+
+    if (result.has("voice_credentials"))
+    {
+        LLSD voice_credentials = result["voice_credentials"];
+        if (voice_credentials.has("channel_uri"))
+        {
+            uri = voice_credentials["channel_uri"].asString();
+        }
+        if (voice_credentials.has("channel_credentials"))
+        {
+            credentials =
+                voice_credentials["channel_credentials"].asString();
+        }
+    }
+
+    LL_INFOS("Voice") << "Voice URI is " << uri << LL_ENDL;
+
+    // set the spatial channel.  If no voice credentials or uri are 
+    // available, then we simply drop out of voice spatially.
+    if (parcelVoiceInfoReceived(requestingState))
+    {
+        setSpatialChannel(uri, credentials);
+    }
+
+}
+
 void LLVivoxVoiceClient::switchChannel(
 	std::string uri,
 	bool spatial,
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index a4ec9f2a69271e0f2a50781653b558722883ae07..b12ed80e41e03c6442c613294489a627157542c4 100755
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -37,6 +37,9 @@ class LLVivoxProtocolParser;
 #include "llframetimer.h"
 #include "llviewerregion.h"
 #include "llcallingcard.h"   // for LLFriendObserver
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include <queue>
 
 #ifdef LL_USESYSTEMLIBS
 # include "expat.h"
@@ -46,7 +49,6 @@ class LLVivoxProtocolParser;
 #include "llvoiceclient.h"
 
 class LLAvatarName;
-class LLVivoxVoiceAccountProvisionResponder;
 class LLVivoxVoiceClientMuteListObserver;
 
 
@@ -251,7 +253,6 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
 	//////////////////////
 	// Vivox Specific definitions	
 	
-	friend class LLVivoxVoiceAccountProvisionResponder;
 	friend class LLVivoxVoiceClientMuteListObserver;
 	friend class LLVivoxVoiceClientFriendsObserver;	
 	
@@ -635,6 +636,10 @@ class LLVivoxVoiceClient :	public LLSingleton<LLVivoxVoiceClient>,
 	void accountGetTemplateFontsResponse(int statusCode, const std::string &statusString); 
 
 private:
+    
+    void voiceAccountProvisionCoro(std::string url, S32 retries);
+    void parcelVoiceInfoRequestCoro(std::string url);
+
 	LLVoiceVersionInfo mVoiceVersion;
 
 	/// Clean up objects created during a voice session.
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0432f6f27c5da75e3fd317ae2b7e0aec9a1c2208..267061b83dd004c309c1e87183a4f20e047a9789 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4172,6 +4172,10 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
 	for (U32 j = 0; j < maxJoints; ++j)
 	{
 		LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+        if (!joint)
+        {
+            joint = avatar->getJoint("mPelvis");
+        }
 		if (joint)
 		{
 			mat[j] = skin->mInvBindMatrix[j];
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index ddb7f7bfce147daf0036ada23bc88734e1ceeacc..06ce4975106b5c3c9742deb48aa8bd4efdf5f70a 100755
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -30,14 +30,17 @@
 
 // libs
 #include "llbufferstream.h"
-#include "llhttpclient.h"
 #include "llimagepng.h"
 #include "llplugincookiestore.h"
 
+#include "llsdserialize.h"
+
 // newview
 #include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions
 #include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals
 
+#include "llcorehttputil.h"
+
 // third-party
 #include "reader.h" // JSON
 
@@ -54,139 +57,6 @@
  *    -> GET <redirect_url> via PostImageRedirectResponder
  */
 
-///////////////////////////////////////////////////////////////////////////////
-// LLWebProfileResponders::ConfigResponder
-
-class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLWebProfileResponders::ConfigResponder);
-
-public:
-	ConfigResponder(LLPointer<LLImageFormatted> imagep)
-	:	mImagep(imagep)
-	{
-	}
-
-	// *TODO: Check for 'application/json' content type, and parse json at the base class.
-	/*virtual*/ void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		LLBufferStream istr(channels, buffer.get());
-		std::stringstream strstrm;
-		strstrm << istr.rdbuf();
-		const std::string body = strstrm.str();
-
-		if (getStatus() != HTTP_OK)
-		{
-			LL_WARNS() << "Failed to get upload config " << dumpResponse() << LL_ENDL;
-			LLWebProfile::reportImageUploadStatus(false);
-			return;
-		}
-
-		Json::Value root;
-		Json::Reader reader;
-		if (!reader.parse(body, root))
-		{
-			LL_WARNS() << "Failed to parse upload config: " << reader.getFormatedErrorMessages() << LL_ENDL;
-			LLWebProfile::reportImageUploadStatus(false);
-			return;
-		}
-
-		// *TODO: 404 = not supported by the grid
-		// *TODO: increase timeout or handle 499 Expired
-
-		// Convert config to LLSD.
-		const Json::Value data = root["data"];
-		const std::string upload_url = root["url"].asString();
-		LLSD config;
-		config["acl"]						= data["acl"].asString();
-		config["AWSAccessKeyId"]			= data["AWSAccessKeyId"].asString();
-		config["Content-Type"]				= data["Content-Type"].asString();
-		config["key"]						= data["key"].asString();
-		config["policy"]					= data["policy"].asString();
-		config["success_action_redirect"]	= data["success_action_redirect"].asString();
-		config["signature"]					= data["signature"].asString();
-		config["add_loc"]					= data.get("add_loc", "0").asString();
-		config["caption"]					= data.get("caption", "").asString();
-
-		// Do the actual image upload using the configuration.
-		LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << LL_ENDL;
-		LLWebProfile::post(mImagep, config, upload_url);
-	}
-
-private:
-	LLPointer<LLImageFormatted> mImagep;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// LLWebProfilePostImageRedirectResponder
-class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLWebProfileResponders::PostImageRedirectResponder);
-
-public:
-	/*virtual*/ void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		if (getStatus() != HTTP_OK)
-		{
-			LL_WARNS() << "Failed to upload image " << dumpResponse() << LL_ENDL;
-			LLWebProfile::reportImageUploadStatus(false);
-			return;
-		}
-
-		LLBufferStream istr(channels, buffer.get());
-		std::stringstream strstrm;
-		strstrm << istr.rdbuf();
-		const std::string body = strstrm.str();
-		LL_INFOS() << "Image uploaded." << LL_ENDL;
-		LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << LL_ENDL;
-		LLWebProfile::reportImageUploadStatus(true);
-	}
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// LLWebProfileResponders::PostImageResponder
-class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLWebProfileResponders::PostImageResponder);
-
-public:
-	/*virtual*/ void completedRaw(const LLChannelDescriptors& channels,
-								  const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// Viewer seems to fail to follow a 303 redirect on POST request
-		// (URLRequest Error: 65, Send failed since rewinding of the data stream failed).
-		// Handle it manually.
-		if (getStatus() == HTTP_SEE_OTHER)
-		{
-			LLSD headers = LLViewerMedia::getHeaders();
-			headers[HTTP_OUT_HEADER_COOKIE] = LLWebProfile::getAuthCookie();
-			const std::string& redir_url = getResponseHeader(HTTP_IN_HEADER_LOCATION);
-			if (redir_url.empty())
-			{
-				LL_WARNS() << "Received empty redirection URL " << dumpResponse() << LL_ENDL;
-				LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-				LLWebProfile::reportImageUploadStatus(false);
-			}
-			else
-			{
-				LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << LL_ENDL;
-				LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers);
-			}
-		}
-		else
-		{
-			LL_WARNS() << "Unexpected POST response " << dumpResponse() << LL_ENDL;
-			LL_DEBUGS("Snapshots") << "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
-			LLWebProfile::reportImageUploadStatus(false);
-		}
-	}
-};
-
 ///////////////////////////////////////////////////////////////////////////////
 // LLWebProfile
 
@@ -196,15 +66,9 @@ LLWebProfile::status_callback_t LLWebProfile::mStatusCallback;
 // static
 void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::string& caption, bool add_location)
 {
-	// Get upload configuration data.
-	std::string config_url(getProfileURL(LLStringUtil::null) + "snapshots/s3_upload_config");
-	config_url += "?caption=" + LLURI::escape(caption);
-	config_url += "&add_loc=" + std::string(add_location ? "1" : "0");
-
-	LL_DEBUGS("Snapshots") << "Requesting " << config_url << LL_ENDL;
-	LLSD headers = LLViewerMedia::getHeaders();
-	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
-	LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers);
+    LLCoros::instance().launch("LLWebProfile::uploadImageCoro",
+        boost::bind(&LLWebProfile::uploadImageCoro, image, caption, add_location));
+
 }
 
 // static
@@ -214,74 +78,178 @@ void LLWebProfile::setAuthCookie(const std::string& cookie)
 	sAuthCookie = cookie;
 }
 
-// static
-void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url)
+
+/*static*/
+LLCore::HttpHeaders::ptr_t LLWebProfile::buildDefaultHeaders()
 {
-	if (dynamic_cast<LLImagePNG*>(image.get()) == 0)
-	{
-		LL_WARNS() << "Image to upload is not a PNG" << LL_ENDL;
-		llassert(dynamic_cast<LLImagePNG*>(image.get()) != 0);
-		return;
-	}
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    LLSD headers = LLViewerMedia::getHeaders();
 
-	const std::string boundary = "----------------------------0123abcdefab";
+    for (LLSD::map_iterator it = headers.beginMap(); it != headers.endMap(); ++it)
+    {
+        httpHeaders->append((*it).first, (*it).second.asStringRef());
+    }
 
-	LLSD headers = LLViewerMedia::getHeaders();
-	headers[HTTP_OUT_HEADER_COOKIE] = getAuthCookie();
-	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "multipart/form-data; boundary=" + boundary;
+    return httpHeaders;
+}
 
-	std::ostringstream body;
 
-	// *NOTE: The order seems to matter.
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"key\"\r\n\r\n"
-			<< config["key"].asString() << "\r\n";
+/*static*/
+void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> image, std::string caption, bool addLocation)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders;
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\n"
-			<< config["AWSAccessKeyId"].asString() << "\r\n";
+    if (dynamic_cast<LLImagePNG*>(image.get()) == 0)
+    {
+        LL_WARNS() << "Image to upload is not a PNG" << LL_ENDL;
+        llassert(dynamic_cast<LLImagePNG*>(image.get()) != 0);
+        return;
+    }
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"acl\"\r\n\r\n"
-			<< config["acl"].asString() << "\r\n";
+    httpOpts->setWantHeaders(true);
+    httpOpts->setFollowRedirects(false);
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"Content-Type\"\r\n\r\n"
-			<< config["Content-Type"].asString() << "\r\n";
+    // Get upload configuration data.
+    std::string configUrl(getProfileURL(std::string()) + "snapshots/s3_upload_config");
+    configUrl += "?caption=" + LLURI::escape(caption);
+    configUrl += "&add_loc=" + std::string(addLocation ? "1" : "0");
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"policy\"\r\n\r\n"
-			<< config["policy"].asString() << "\r\n";
+    LL_DEBUGS("Snapshots") << "Requesting " << configUrl << LL_ENDL;
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"signature\"\r\n\r\n"
-			<< config["signature"].asString() << "\r\n";
+    httpHeaders = buildDefaultHeaders();
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, getAuthCookie());
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"success_action_redirect\"\r\n\r\n"
-			<< config["success_action_redirect"].asString() << "\r\n";
+    LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, configUrl, httpOpts, httpHeaders);
 
-	body	<< "--" << boundary << "\r\n"
-			<< "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
-			<< "Content-Type: image/png\r\n\r\n";
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-	// Insert the image data.
-	// *FIX: Treating this as a string will probably screw it up ...
-	U8* image_data = image->getData();
-	for (S32 i = 0; i < image->getDataSize(); ++i)
-	{
-		body << image_data[i];
-	}
+    if (!status)
+    {
+        LL_WARNS("Snapshots") << "Failed to get image upload config" << LL_ENDL;
+        LLWebProfile::reportImageUploadStatus(false);
+        return;
+    }
+
+    // Ready to build our image post body.
+
+    const LLSD &data = result["data"];
+    const std::string &uploadUrl = result["url"].asStringRef();
+    const std::string boundary = "----------------------------0123abcdefab";
+
+    // a new set of headers.
+    httpHeaders = LLWebProfile::buildDefaultHeaders();
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, getAuthCookie());
+    httpHeaders->remove(HTTP_OUT_HEADER_CONTENT_TYPE);
+    httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
+    
+    LLCore::BufferArray::ptr_t body = LLWebProfile::buildPostData(data, image, boundary);
+
+    result = httpAdapter->postAndSuspend(httpRequest, uploadUrl, body, httpOpts, httpHeaders);
+
+    body.reset();
+    httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
 
-	body <<	"\r\n--" << boundary << "--\r\n";
+    if (!status && (status != LLCore::HttpStatus(HTTP_SEE_OTHER)))
+    {
+        LL_WARNS("Snapshots") << "Failed to upload image data." << LL_ENDL;
+        LLWebProfile::reportImageUploadStatus(false);
+        return;
+    }
 
-	// postRaw() takes ownership of the buffer and releases it later.
-	size_t size = body.str().size();
-	U8 *data = new U8[size];
-	memcpy(data, body.str().data(), size);
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
 
-	// Send request, successful upload will trigger posting metadata.
-	LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers);
+    httpHeaders = LLWebProfile::buildDefaultHeaders();
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, getAuthCookie());
+
+    const std::string& redirUrl = resultHeaders[HTTP_IN_HEADER_LOCATION].asStringRef();
+
+    if (redirUrl.empty())
+    {
+        LL_WARNS("Snapshots") << "Received empty redirection URL in post image." << LL_ENDL;
+        LLWebProfile::reportImageUploadStatus(false);
+    }
+
+    LL_DEBUGS("Snapshots") << "Got redirection URL: " << redirUrl << LL_ENDL;
+
+    result = httpAdapter->getRawAndSuspend(httpRequest, redirUrl, httpOpts, httpHeaders);
+
+    httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (status != LLCore::HttpStatus(HTTP_OK))
+    {
+        LL_WARNS("Snapshots") << "Failed to upload image." << LL_ENDL;
+        LLWebProfile::reportImageUploadStatus(false);
+        return;
+    }
+
+    //LLSD raw = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW];
+
+    LL_INFOS("Snapshots") << "Image uploaded." << LL_ENDL;
+    //LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << raw.asString() << "]" << LL_ENDL;
+    LLWebProfile::reportImageUploadStatus(true);
+
+
+}
+
+/*static*/
+LLCore::BufferArray::ptr_t LLWebProfile::buildPostData(const LLSD &data, LLPointer<LLImageFormatted> &image, const std::string &boundary)
+{
+    LLCore::BufferArray::ptr_t body(new LLCore::BufferArray);
+    LLCore::BufferArrayStream bas(body.get());
+
+    // *NOTE: The order seems to matter.
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"key\"\r\n\r\n"
+        << data["key"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\n"
+        << data["AWSAccessKeyId"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"acl\"\r\n\r\n"
+        << data["acl"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"Content-Type\"\r\n\r\n"
+        << data["Content-Type"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"policy\"\r\n\r\n"
+        << data["policy"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"signature\"\r\n\r\n"
+        << data["signature"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"success_action_redirect\"\r\n\r\n"
+        << data["success_action_redirect"].asString() << "\r\n";
+
+    bas << "--" << boundary << "\r\n"
+        << "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.png\"\r\n"
+        << "Content-Type: image/png\r\n\r\n";
+
+    // Insert the image data.
+    //char *datap = (char *)(image->getData());
+    //bas.write(datap, image->getDataSize());
+    U8* image_data = image->getData();
+    for (S32 i = 0; i < image->getDataSize(); ++i)
+    {
+        bas << image_data[i];
+    }
+
+    bas << "\r\n--" << boundary << "--\r\n";
+
+    return body;
 }
 
 // static
diff --git a/indra/newview/llwebprofile.h b/indra/newview/llwebprofile.h
index 10279bffaccfe3c225c59bf81de225d39f0101c2..6227e00afeab80e7d872e2f76a256e4eb9545d83 100755
--- a/indra/newview/llwebprofile.h
+++ b/indra/newview/llwebprofile.h
@@ -28,6 +28,10 @@
 #define LL_LLWEBPROFILE_H
 
 #include "llimage.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "httpheaders.h"
+#include "bufferarray.h"
 
 namespace LLWebProfileResponders
 {
@@ -54,11 +58,11 @@ class LLWebProfile
 	static void setImageUploadResultCallback(status_callback_t cb) { mStatusCallback = cb; }
 
 private:
-	friend class LLWebProfileResponders::ConfigResponder;
-	friend class LLWebProfileResponders::PostImageResponder;
-	friend class LLWebProfileResponders::PostImageRedirectResponder;
+    static LLCore::HttpHeaders::ptr_t buildDefaultHeaders();
+
+    static void uploadImageCoro(LLPointer<LLImageFormatted> image, std::string caption, bool add_location);
+    static LLCore::BufferArray::ptr_t buildPostData(const LLSD &data, LLPointer<LLImageFormatted> &image, const std::string &boundary);
 
-	static void post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url);
 	static void reportImageUploadStatus(bool ok);
 	static std::string getAuthCookie();
 
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index 3bedfbe502af09f22717da6c035bf5e8e7c47c96..87e8c3008e0d98cf5de505351d4897e3db237391 100755
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -32,6 +32,7 @@
 #include "llviewerregion.h"
 #include "llenvmanager.h"
 #include "llnotificationsutil.h"
+#include "llcorehttputil.h"
 
 /****
  * LLEnvironmentRequest
@@ -81,55 +82,62 @@ bool LLEnvironmentRequest::doRequest()
 		return false;
 	}
 
-	LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
-	LLHTTPClient::get(url, new LLEnvironmentRequestResponder());
-	return true;
-}
-
-/****
- * LLEnvironmentRequestResponder
- ****/
-int LLEnvironmentRequestResponder::sCount = 0; // init to 0
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironmentRequest::environmentRequestCoro",
+        boost::bind(&LLEnvironmentRequest::environmentRequestCoro, url));
 
-LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
-{
-	mID = ++sCount;
+    LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
+    return true;
 }
-/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess()
-{
-	const LLSD& unvalidated_content = getContent();
-	LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
 
-	if (mID != sCount)
-	{
-		LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
-		return;
-	}
-
-	LLUUID regionId;
-	if( gAgent.getRegion() )
-	{
-		regionId = gAgent.getRegion()->getRegionID();
-	}
-	
-	if (unvalidated_content[0]["regionID"].asUUID() != regionId )
-	{
-		LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
-			<< regionId << " but got " << unvalidated_content[0]["regionID"].asUUID()
-			<< ") - ignoring..." << LL_ENDL;
-		return;
-	}
+S32 LLEnvironmentRequest::sLastRequest = 0;
 
-	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content);
-}
-/*virtual*/
-void LLEnvironmentRequestResponder::httpFailure()
+//static 
+void LLEnvironmentRequest::environmentRequestCoro(std::string url)
 {
-	LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... "
-			<< dumpResponse() << LL_ENDL;
-	LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    S32 requestId = ++LLEnvironmentRequest::sLastRequest;
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t 
+            httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    if (requestId != LLEnvironmentRequest::sLastRequest)
+    {
+        LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
+        return;
+    }
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    if (!status)
+    {
+        LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " << LL_ENDL;
+        LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
+        return;
+    }
+    result = result["content"];
+    LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
+
+    LLUUID regionId;
+    if (gAgent.getRegion())
+    {
+        regionId = gAgent.getRegion()->getRegionID();
+    }
+
+    if ((result[0]["regionID"].asUUID() != regionId) && regionId.notNull())
+    {
+        LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
+            << regionId << " but got " << result[0]["regionID"].asUUID()
+            << ") - ignoring..." << LL_ENDL;
+        return;
+    }
+
+    LLEnvManagerNew::getInstance()->onRegionSettingsResponse(result);
 }
 
+
 /****
  * LLEnvironmentApply
  ****/
@@ -161,53 +169,86 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 		return false;
 	}
 
-	LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL;
-	LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL;
-	LLHTTPClient::post(url, content, new LLEnvironmentApplyResponder());
+    LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL;
+    LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL;
+
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironmentApply::environmentApplyCoro",
+        boost::bind(&LLEnvironmentApply::environmentApplyCoro, url, content));
 	return true;
 }
 
-/****
- * LLEnvironmentApplyResponder
- ****/
-/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess()
-{
-	const LLSD& content = getContent();
-	if (!content.isMap() || !content.has("regionID"))
-	{
-		failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
-		return;
-	}
-	if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
-	{
-		LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
-			<< gAgent.getRegion()->getRegionID() << ", reply is from " << content["regionID"].asUUID()
-			<< "); ignoring..." << LL_ENDL;
-		return;
-	}
-	else if (content["success"].asBoolean())
-	{
-		LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << content["regionID"].asUUID() << LL_ENDL;
-		LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
-	}
-	else
-	{
-		LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << dumpResponse() << LL_ENDL;
-		LLSD args(LLSD::emptyMap());
-		args["FAIL_REASON"] = content["fail_reason"].asString();
-		LLNotificationsUtil::add("WLRegionApplyFail", args);
-		LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
-	}
-}
-/*virtual*/
-void LLEnvironmentApplyResponder::httpFailure()
+void LLEnvironmentApply::environmentApplyCoro(std::string url, LLSD content)
 {
-	LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! "
-		<< dumpResponse() << LL_ENDL;
-
-	LLSD args(LLSD::emptyMap());
-	std::stringstream msg;
-	msg << getReason() << " (Code " << getStatus() << ")";
-	args["FAIL_REASON"] = msg.str();
-	LLNotificationsUtil::add("WLRegionApplyFail", args);
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentApply", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LLSD result = httpAdapter->postAndSuspend(httpRequest, url, content);
+
+    LLSD notify; // for error reporting.  If there is something to report to user this will be defined.
+    /*
+     * Expecting reply from sim in form of:
+     * {
+     *   regionID : uuid,
+     *   messageID: uuid,
+     *   success : true
+     * }
+     * or
+     * {
+     *   regionID : uuid,
+     *   success : false,
+     *   fail_reason : string
+     * }
+     */
+
+    do // while false.  
+    {  // Breaks from loop in the case of an error.
+
+        LLSD httpResults = result["http_result"];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+        if (!status)
+        {
+            LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " << LL_ENDL;
+
+            std::stringstream msg;
+            msg << status.toString() << " (Code " << status.toTerseString() << ")";
+            notify = LLSD::emptyMap();
+            notify["FAIL_REASON"] = msg.str();
+            break;
+        }
+
+        if (!result.has("regionID"))
+        {
+            notify = LLSD::emptyMap();
+            notify["FAIL_REASON"] = "Missing regionID, malformed response";
+            break;
+        } 
+        else if (result["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
+        {
+            // note that there is no report to the user in this failure case.
+            LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
+                << gAgent.getRegion()->getRegionID() << ", reply is from " << result["regionID"].asUUID()
+                << "); ignoring..." << LL_ENDL;
+            break;
+        }
+        else if (!result["success"].asBoolean())
+        {
+            LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings!  " << LL_ENDL;
+            notify = LLSD::emptyMap();
+            notify["FAIL_REASON"] = result["fail_reason"].asString();
+            break;
+        }
+
+        LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << result["regionID"].asUUID() << LL_ENDL;
+        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
+
+    } while (false);
+
+    if (!notify.isUndefined())
+    {
+        LLNotificationsUtil::add("WLRegionApplyFail", notify);
+        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
+    }
 }
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
index 089c799da7cac21dd37228c41411fe0acd7854f4..eb2bbf9553596d85f38e1c4e9e31a4f64dc6c1fc 100755
--- a/indra/newview/llwlhandlers.h
+++ b/indra/newview/llwlhandlers.h
@@ -28,7 +28,7 @@
 #define LL_LLWLHANDLERS_H
 
 #include "llviewerprecompiledheaders.h"
-#include "llhttpclient.h"
+#include "llcoros.h"
 
 class LLEnvironmentRequest
 {
@@ -40,21 +40,10 @@ class LLEnvironmentRequest
 private:
 	static void onRegionCapsReceived(const LLUUID& region_id);
 	static bool doRequest();
-};
-
-class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLEnvironmentRequestResponder);
-private:
-	/* virtual */ void httpSuccess();
-	/* virtual */ void httpFailure();
 
-private:
-	friend class LLEnvironmentRequest;
+    static void environmentRequestCoro(std::string url);
 
-	LLEnvironmentRequestResponder();
-	static int sCount;
-	int mID;
+    static S32 sLastRequest;
 };
 
 class LLEnvironmentApply
@@ -67,35 +56,8 @@ class LLEnvironmentApply
 private:
 	static clock_t sLastUpdate;
 	static clock_t UPDATE_WAIT_SECONDS;
-};
 
-class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLEnvironmentApplyResponder);
-private:
-	/*
-	 * Expecting reply from sim in form of:
-	 * {
-	 *   regionID : uuid,
-	 *   messageID: uuid,
-	 *   success : true
-	 * }
-	 * or
-	 * {
-	 *   regionID : uuid,
-	 *   success : false,
-	 *   fail_reason : string
-	 * }
-	 */
-	/* virtual */ void httpSuccess();
-
-	// non-2xx errors only
-	/* virtual */ void httpFailure();
-
-private:
-	friend class LLEnvironmentApply;
-	
-	LLEnvironmentApplyResponder() {}
+    static void environmentApplyCoro(std::string url, LLSD content);
 };
 
 #endif // LL_LLWLHANDLERS_H
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index c12c2cc24c3639c8e020d0e6ec788246e61677b5..442ed73c2dd4f81fd2a43e774d4c8dc25cc74d42 100755
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -34,7 +34,12 @@
 #include "llxmlrpctransaction.h"
 #include "llxmlrpclistener.h"
 
-#include "llcurl.h"
+#include "httpcommon.h"
+#include "llhttpconstants.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+#include "httpheaders.h"
+#include "bufferarray.h"
 #include "llviewercontrol.h"
 
 // Have to include these last to avoid queue redefinition!
@@ -43,6 +48,13 @@
 #include "llappviewer.h"
 #include "lltrans.h"
 
+#include "boost/move/unique_ptr.hpp"
+
+namespace boost
+{
+	using ::boost::movelib::unique_ptr; // move unique_ptr into the boost namespace.
+}
+
 // Static instance of LLXMLRPCListener declared here so that every time we
 // bring in this code, we instantiate a listener. If we put the static
 // instance of LLXMLRPCListener into llxmlrpclistener.cpp, the linker would
@@ -155,55 +167,158 @@ XMLRPC_VALUE LLXMLRPCValue::getValue() const
 }
 
 
+class LLXMLRPCTransaction::Handler : public LLCore::HttpHandler
+{
+public: 
+	Handler(LLCore::HttpRequest::ptr_t &request, LLXMLRPCTransaction::Impl *impl);
+	virtual ~Handler();
+
+	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+	typedef boost::unique_ptr<LLXMLRPCTransaction::Handler> ptr_t;
+
+private:
+
+	LLXMLRPCTransaction::Impl *mImpl;
+	LLCore::HttpRequest::ptr_t mRequest;
+};
+
 class LLXMLRPCTransaction::Impl
 {
 public:
 	typedef LLXMLRPCTransaction::EStatus	EStatus;
 
-	LLCurlEasyRequest* mCurlRequest;
+	LLCore::HttpRequest::ptr_t	mHttpRequest;
+
+
+	EStatus				mStatus;
+	CURLcode			mCurlCode;
+	std::string			mStatusMessage;
+	std::string			mStatusURI;
+	LLCore::HttpResponse::TransferStats::ptr_t	mTransferStats;
+	Handler::ptr_t		mHandler;
+	LLCore::HttpHandle	mPostH;
 
-	EStatus		mStatus;
-	CURLcode	mCurlCode;
-	std::string	mStatusMessage;
-	std::string	mStatusURI;
-	LLCurl::TransferInfo mTransferInfo;
-	
 	std::string			mURI;
-	char*				mRequestText;
-	int					mRequestTextSize;
-	
+
 	std::string			mProxyAddress;
 
 	std::string			mResponseText;
 	XMLRPC_REQUEST		mResponse;
 	std::string         mCertStore;
 	LLPointer<LLCertificate> mErrorCert;
-	
+
 	Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
 	Impl(const std::string& uri,
-		 const std::string& method, LLXMLRPCValue params, bool useGzip);
+		const std::string& method, LLXMLRPCValue params, bool useGzip);
 	~Impl();
-	
+
 	bool process();
-	
-	void setStatus(EStatus code,
-				   const std::string& message = "", const std::string& uri = "");
-	void setCurlStatus(CURLcode);
+
+	void setStatus(EStatus code, const std::string& message = "", const std::string& uri = "");
+	void setHttpStatus(const LLCore::HttpStatus &status);
 
 private:
 	void init(XMLRPC_REQUEST request, bool useGzip);
-	static int _sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
-	static CURLcode _sslCtxFunction(CURL * curl, void *sslctx, void *param);
-	static size_t curlDownloadCallback(
-		char* data, size_t size, size_t nmemb, void* user_data);
 };
 
+LLXMLRPCTransaction::Handler::Handler(LLCore::HttpRequest::ptr_t &request, 
+		LLXMLRPCTransaction::Impl *impl) :
+	mImpl(impl),
+	mRequest(request)
+{
+}
+
+LLXMLRPCTransaction::Handler::~Handler()
+{
+}
+
+void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle, 
+	LLCore::HttpResponse * response)
+{
+	LLCore::HttpStatus status = response->getStatus();
+
+	if (!status)
+	{
+		if ((status.toULong() != CURLE_SSL_PEER_CERTIFICATE) &&
+			(status.toULong() != CURLE_SSL_CACERT))
+		{
+			// if we have a curl error that's not already been handled
+			// (a non cert error), then generate the error message as
+			// appropriate
+			mImpl->setHttpStatus(status);
+			LLCertificate *errordata = static_cast<LLCertificate *>(status.getErrorData());
+
+			if (errordata)
+			{
+				mImpl->mErrorCert = LLPointer<LLCertificate>(errordata);
+				status.setErrorData(NULL);
+				errordata->unref();
+			}
+
+			LL_WARNS() << "LLXMLRPCTransaction error "
+				<< status.toHex() << ": " << status.toString() << LL_ENDL;
+			LL_WARNS() << "LLXMLRPCTransaction request URI: "
+				<< mImpl->mURI << LL_ENDL;
+		}
+
+		return;
+	}
+
+	mImpl->setStatus(LLXMLRPCTransaction::StatusComplete);
+	mImpl->mTransferStats = response->getTransferStats();
+
+	// the contents of a buffer array are potentially noncontiguous, so we
+	// will need to copy them into an contiguous block of memory for XMLRPC.
+	LLCore::BufferArray *body = response->getBody();
+	char * bodydata = new char[body->size()];
+
+	body->read(0, bodydata, body->size());
+
+	mImpl->mResponse = XMLRPC_REQUEST_FromXML(bodydata, body->size(), 0);
+
+	delete[] bodydata;
+
+	bool		hasError = false;
+	bool		hasFault = false;
+	int			faultCode = 0;
+	std::string	faultString;
+
+	LLXMLRPCValue error(XMLRPC_RequestGetError(mImpl->mResponse));
+	if (error.isValid())
+	{
+		hasError = true;
+		faultCode = error["faultCode"].asInt();
+		faultString = error["faultString"].asString();
+	}
+	else if (XMLRPC_ResponseIsFault(mImpl->mResponse))
+	{
+		hasFault = true;
+		faultCode = XMLRPC_GetResponseFaultCode(mImpl->mResponse);
+		faultString = XMLRPC_GetResponseFaultString(mImpl->mResponse);
+	}
+
+	if (hasError || hasFault)
+	{
+		mImpl->setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
+
+		LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
+			<< (hasError ? "error " : "fault ")
+			<< faultCode << ": "
+			<< faultString << LL_ENDL;
+		LL_WARNS() << "LLXMLRPCTransaction request URI: "
+			<< mImpl->mURI << LL_ENDL;
+	}
+
+}
+
+//=========================================================================
+
 LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
 		XMLRPC_REQUEST request, bool useGzip)
-	: mCurlRequest(0),
+	: mHttpRequest(),
 	  mStatus(LLXMLRPCTransaction::StatusNotStarted),
 	  mURI(uri),
-	  mRequestText(0), 
 	  mResponse(0)
 {
 	init(request, useGzip);
@@ -212,10 +327,9 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
 
 LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
 		const std::string& method, LLXMLRPCValue params, bool useGzip)
-	: mCurlRequest(0),
+	: mHttpRequest(),
 	  mStatus(LLXMLRPCTransaction::StatusNotStarted),
 	  mURI(uri),
-	  mRequestText(0), 
 	  mResponse(0)
 {
 	XMLRPC_REQUEST request = XMLRPC_RequestNew();
@@ -231,127 +345,53 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
     XMLRPC_RequestFree(request, 1);
 }
 
-// _sslCertVerifyCallback
-// callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-int LLXMLRPCTransaction::Impl::_sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
+void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
 {
-	LLXMLRPCTransaction::Impl *transaction = (LLXMLRPCTransaction::Impl *)param;
-	LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore(transaction->mCertStore);
-	LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
-	LLSD validation_params = LLSD::emptyMap();
-	LLURI uri(transaction->mURI);
-	validation_params[CERT_HOSTNAME] = uri.hostName();
-	try
-	{
-		// don't validate hostname.  Let libcurl do it instead.  That way, it'll handle redirects
-		store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
-	}
-	catch (LLCertValidationTrustException& cert_exception)
-	{
-		// this exception is is handled differently than the general cert
-		// exceptions, as we allow the user to actually add the certificate
-		// for trust.
-		// therefore we pass back a different error code
-		// NOTE: We're currently 'wired' to pass around CURL error codes.  This is
-		// somewhat clumsy, as we may run into errors that do not map directly to curl
-		// error codes.  Should be refactored with login refactoring, perhaps.
-		transaction->mCurlCode = CURLE_SSL_CACERT;
-		// set the status directly.  set curl status generates error messages and we want
-		// to use the fixed ones from the exceptions
-		transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
-		// We should probably have a more generic way of passing information
-		// back to the error handlers.
-		transaction->mErrorCert = cert_exception.getCert();
-		return 0;		
-	}
-	catch (LLCertException& cert_exception)
-	{
-		transaction->mCurlCode = CURLE_SSL_PEER_CERTIFICATE;
-		// set the status directly.  set curl status generates error messages and we want
-		// to use the fixed ones from the exceptions
-		transaction->setStatus(StatusCURLError, cert_exception.getMessage(), std::string());
-		transaction->mErrorCert = cert_exception.getCert();
-		return 0;
-	}
-	catch (...)
-	{
-		// any other odd error, we just handle as a connect error.
-		transaction->mCurlCode = CURLE_SSL_CONNECT_ERROR;
-		transaction->setCurlStatus(CURLE_SSL_CONNECT_ERROR);
-		return 0;
-	}
-	return 1;
-}
+	LLCore::HttpOptions::ptr_t httpOpts;
+	LLCore::HttpHeaders::ptr_t httpHeaders;
 
-// _sslCtxFunction
-// Callback function called when an SSL Context is created via CURL
-// used to configure the context for custom cert validate(<, <#const & xs#>, <#T * #>, <#long #>)tion
-// based on SECAPI
-
-CURLcode LLXMLRPCTransaction::Impl::_sslCtxFunction(CURL * curl, void *sslctx, void *param)
-{
-	SSL_CTX * ctx = (SSL_CTX *) sslctx;
-	// disable any default verification for server certs
-	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
-	// set the verification callback.
-	SSL_CTX_set_cert_verify_callback(ctx, _sslCertVerifyCallback, param);
-	// the calls are void
-	return CURLE_OK;
-	
-}
 
-void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
-{
-	if (!mCurlRequest)
+	if (!mHttpRequest)
 	{
-		mCurlRequest = new LLCurlEasyRequest();
+		mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
 	}
-	if(!mCurlRequest->isValid())
-	{
-		LL_WARNS() << "mCurlRequest is invalid." << LL_ENDL ;
 
-		delete mCurlRequest ;
-		mCurlRequest = NULL ;
-		return ;
-	}
+	// LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+	httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); 
 
-	mErrorCert = NULL;
+	httpOpts->setTimeout(40L);
 
-//	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging
-	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
-	mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
-	BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
+	bool vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
 	mCertStore = gSavedSettings.getString("CertStore");
-	mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
-	mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
-	// Be a little impatient about establishing connections.
-	mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);
-	mCurlRequest->setSSLCtxCallback(_sslCtxFunction, (void *)this);
 
-	/* Setting the DNS cache timeout to -1 disables it completely.
-	   This might help with bug #503 */
-	mCurlRequest->setopt(CURLOPT_DNS_CACHE_TIMEOUT, -1);
+	httpOpts->setSSLVerifyPeer( vefifySSLCert );
+	httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0);
 
-    mCurlRequest->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+	// LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
+	httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
 
-	if (useGzip)
-	{
-		mCurlRequest->setoptString(CURLOPT_ENCODING, "");
-	}
+	httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
+
+	///* Setting the DNS cache timeout to -1 disables it completely.
+	//This might help with bug #503 */
+	//httpOpts->setDNSCacheTimeout(-1);
+
+	LLCore::BufferArray::ptr_t body = LLCore::BufferArray::ptr_t(new LLCore::BufferArray());
+
+	// TODO: See if there is a way to serialize to a preallocated buffer I'm 
+	// not fond of the copy here.
+	int	requestSize(0);
+	char * requestText = XMLRPC_REQUEST_ToXML(request, &requestSize);
+
+	body->append(requestText, requestSize);
 	
-	mRequestText = XMLRPC_REQUEST_ToXML(request, &mRequestTextSize);
-	if (mRequestText)
-	{
-		mCurlRequest->setoptString(CURLOPT_POSTFIELDS, mRequestText);
-		mCurlRequest->setopt(CURLOPT_POSTFIELDSIZE, mRequestTextSize);
-	}
-	else
-	{
-		setStatus(StatusOtherError);
-	}
+	XMLRPC_Free(requestText);
+
+	mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
+
+	mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0, 
+		mURI, body.get(), httpOpts, httpHeaders, mHandler.get());
 
-	mCurlRequest->sendRequest(mURI);
 }
 
 
@@ -361,28 +401,17 @@ LLXMLRPCTransaction::Impl::~Impl()
 	{
 		XMLRPC_RequestFree(mResponse, 1);
 	}
-	
-	if (mRequestText)
-	{
-		XMLRPC_Free(mRequestText);
-	}
-	
-	delete mCurlRequest;
-	mCurlRequest = NULL ;
 }
 
 bool LLXMLRPCTransaction::Impl::process()
 {
-	if(!mCurlRequest || !mCurlRequest->isValid())
+	if (!mPostH || !mHttpRequest)
 	{
-		LL_WARNS() << "transaction failed." << LL_ENDL ;
-
-		delete mCurlRequest ;
-		mCurlRequest = NULL ;
-		return true ; //failed, quit.
+		LL_WARNS() << "transaction failed." << LL_ENDL;
+		return true; //failed, quit.
 	}
 
-	switch(mStatus)
+	switch (mStatus)
 	{
 		case LLXMLRPCTransaction::StatusComplete:
 		case LLXMLRPCTransaction::StatusCURLError:
@@ -391,93 +420,25 @@ bool LLXMLRPCTransaction::Impl::process()
 		{
 			return true;
 		}
-		
+
 		case LLXMLRPCTransaction::StatusNotStarted:
 		{
 			setStatus(LLXMLRPCTransaction::StatusStarted);
 			break;
 		}
-		
+
 		default:
-		{
-			// continue onward
-		}
-	}
-		
-	if(!mCurlRequest->wait())
-	{
-		return false ;
+			break;
 	}
 
-	while(1)
-	{
-		CURLcode result;
-		bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
-		if (newmsg)
-		{
-			if (result != CURLE_OK)
-			{
-				if ((result != CURLE_SSL_PEER_CERTIFICATE) &&
-					(result != CURLE_SSL_CACERT))
-				{
-					// if we have a curl error that's not already been handled
-					// (a non cert error), then generate the error message as
-					// appropriate
-					setCurlStatus(result);
-				
-					LL_WARNS() << "LLXMLRPCTransaction CURL error "
-					<< mCurlCode << ": " << mCurlRequest->getErrorString() << LL_ENDL;
-					LL_WARNS() << "LLXMLRPCTransaction request URI: "
-					<< mURI << LL_ENDL;
-				}
-					
-				return true;
-			}
-			
-			setStatus(LLXMLRPCTransaction::StatusComplete);
+	LLCore::HttpStatus status = mHttpRequest->update(0);
 
-			mResponse = XMLRPC_REQUEST_FromXML(
-					mResponseText.data(), mResponseText.size(), NULL);
-
-			bool		hasError = false;
-			bool		hasFault = false;
-			int			faultCode = 0;
-			std::string	faultString;
-
-			LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
-			if (error.isValid())
-			{
-				hasError = true;
-				faultCode = error["faultCode"].asInt();
-				faultString = error["faultString"].asString();
-			}
-			else if (XMLRPC_ResponseIsFault(mResponse))
-			{
-				hasFault = true;
-				faultCode = XMLRPC_GetResponseFaultCode(mResponse);
-				faultString = XMLRPC_GetResponseFaultString(mResponse);
-			}
-
-			if (hasError || hasFault)
-			{
-				setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
-				
-				LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
-						<< (hasError ? "error " : "fault ")
-						<< faultCode << ": "
-						<< faultString << LL_ENDL;
-				LL_WARNS() << "LLXMLRPCTransaction request URI: "
-						<< mURI << LL_ENDL;
-			}
-			
-			return true;
-		}
-		else
-		{
-			break; // done
-		}
+	status = mHttpRequest->getStatus();
+	if (!status) 
+	{
+		return false;
 	}
-	
+
 	return false;
 }
 
@@ -516,64 +477,51 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
 	}
 }
 
-void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code)
+void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
 {
+	CURLcode code = static_cast<CURLcode>(status.toULong());
 	std::string message;
 	std::string uri = "http://secondlife.com/community/support.php";
-	
+	LLURI failuri(mURI);
+
+
 	switch (code)
 	{
-		case CURLE_COULDNT_RESOLVE_HOST:
-			message =
-				"DNS could not resolve the host name.\n"
-				"Please verify that you can connect to the www.secondlife.com\n"
-				"web site.  If you can, but continue to receive this error,\n"
-				"please go to the support section and report this problem.";
-			break;
-			
-		case CURLE_SSL_PEER_CERTIFICATE:
-			message =
-				"The login server couldn't verify itself via SSL.\n"
-				"If you continue to receive this error, please go\n"
-				"to the Support section of the SecondLife.com web site\n"
-				"and report the problem.";
-			break;
-			
-		case CURLE_SSL_CACERT:
-		case CURLE_SSL_CONNECT_ERROR:
-			message =
-				"Often this means that your computer\'s clock is set incorrectly.\n"
-				"Please go to Control Panels and make sure the time and date\n"
-				"are set correctly.\n"
-				"Also check that your network and firewall are set up correctly.\n"
-				"If you continue to receive this error, please go\n"
-				"to the Support section of the SecondLife.com web site\n"
-				"and report the problem.";
-			break;
-			
-		default:
-				break;
+	case CURLE_COULDNT_RESOLVE_HOST:
+		message =
+			std::string("DNS could not resolve the host name(") + failuri.hostName() + ").\n"
+			"Please verify that you can connect to the www.secondlife.com\n"
+			"web site.  If you can, but continue to receive this error,\n"
+			"please go to the support section and report this problem.";
+		break;
+
+	case CURLE_SSL_PEER_CERTIFICATE:
+		message =
+			"The login server couldn't verify itself via SSL.\n"
+			"If you continue to receive this error, please go\n"
+			"to the Support section of the SecondLife.com web site\n"
+			"and report the problem.";
+		break;
+
+	case CURLE_SSL_CACERT:
+	case CURLE_SSL_CONNECT_ERROR:
+		message =
+			"Often this means that your computer\'s clock is set incorrectly.\n"
+			"Please go to Control Panels and make sure the time and date\n"
+			"are set correctly.\n"
+			"Also check that your network and firewall are set up correctly.\n"
+			"If you continue to receive this error, please go\n"
+			"to the Support section of the SecondLife.com web site\n"
+			"and report the problem.";
+		break;
+
+	default:
+		break;
 	}
-	
+
 	mCurlCode = code;
 	setStatus(StatusCURLError, message, uri);
-}
-
-size_t LLXMLRPCTransaction::Impl::curlDownloadCallback(
-		char* data, size_t size, size_t nmemb, void* user_data)
-{
-	Impl& impl(*(Impl*)user_data);
-	
-	size_t n = size * nmemb;
 
-	impl.mResponseText.append(data, n);
-	
-	if (impl.mStatus == LLXMLRPCTransaction::StatusStarted)
-	{
-		impl.setStatus(LLXMLRPCTransaction::StatusDownloading);
-	}
-	
-	return n;
 }
 
 
@@ -645,11 +593,11 @@ F64 LLXMLRPCTransaction::transferRate()
 		return 0.0L;
 	}
 	
-	double rate_bits_per_sec = impl.mTransferInfo.mSpeedDownload * 8.0;
+	double rate_bits_per_sec = impl.mTransferStats->mSpeedDownload * 8.0;
 	
 	LL_INFOS("AppInit") << "Buffer size:   " << impl.mResponseText.size() << " B" << LL_ENDL;
-	LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferInfo.mSizeDownload << " B" << LL_ENDL;
-	LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferInfo.mTotalTime << " s" << LL_ENDL;
+	LL_DEBUGS("AppInit") << "Transfer size: " << impl.mTransferStats->mSizeDownload << " B" << LL_ENDL;
+	LL_DEBUGS("AppInit") << "Transfer time: " << impl.mTransferStats->mTotalTime << " s" << LL_ENDL;
 	LL_INFOS("AppInit") << "Transfer rate: " << rate_bits_per_sec / 1000.0 << " Kb/s" << LL_ENDL;
 
 	return rate_bits_per_sec;
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index f2589c7f411640aa7b5e8f2ff99b518cdd11c0a6..3a1c9c82b70ff9defc42fff2872f456262fe0bae 100755
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -81,7 +81,7 @@ class LLXMLRPCValue
 
 
 class LLXMLRPCTransaction
-	// an asynchronous request and respones via XML-RPC
+	// an asynchronous request and responses via XML-RPC
 {
 public:
 	LLXMLRPCTransaction(const std::string& uri,
@@ -127,7 +127,9 @@ class LLXMLRPCTransaction
 		// only valid if StsatusComplete, otherwise 0.0
 		
 private:
+	class Handler;
 	class Impl;
+
 	Impl& impl;
 };
 
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 03712c1065e31c3ed57b6f0682681020e970d690..57e2faca5becfa1482ddce551dd9f00e1202dc98 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -105,7 +105,6 @@
 #include "llspatialpartition.h"
 #include "llmutelist.h"
 #include "lltoolpie.h"
-#include "llcurl.h"
 #include "llnotifications.h"
 #include "llpathinglib.h"
 #include "llfloaterpathfindingconsole.h"
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index a4acd1df78448e3893d0d822a0d27577e9171881..7183b2f1f9d5d0f6081390fca477258f1cf59fcf 100755
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -31,6 +31,7 @@
   <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string>
   <string name="mesh_status_missing_lod">Missing required level of detail.</string>
   <string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
+  <string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string>
   <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
   <string name="decomposing">Analyzing...</string>
   <string name="simplifying">Simplifying...</string>
@@ -66,7 +67,7 @@
           follows="top|left"
           layout="topleft"
           height="19"
-          max_length_bytes="64"
+          max_length_bytes="63"
           name="description_form"
           prevalidate_callback="ascii"
           top_pad="5"
@@ -1027,19 +1028,19 @@
                   bg_alpha_color="0 0 0 0"
                   bg_opaque_color="0 0 0 0.3"
                   follows="left|top"
-                  height="16"
+                  height="19"
                   layout="topleft"
                   left="18"
                   name="physics info"
-                  top_pad="15"
-                  width="589">
+                  top_pad="12"
+                  width="319">
                     <text
                       follows="top|left"
                       height="15"
                       layout="topleft"
                       left="0"
                       text_color="White"
-                      top_pad="0"
+                      top_pad="3"
                       name="results_text"
                       width="50">
                       Results:
@@ -1077,6 +1078,33 @@
                       Hulls: [HULLS]
                     </text>
                 </panel>
+                <panel
+                 bg_alpha_color="0 0 0 0"
+                 bg_opaque_color="0 0 0 0.3"
+                 follows="left|top"
+                 height="19"
+                 layout="topleft"
+                 left_pad="5"
+                 top_delta="0"
+                 name="physics message"
+                 width="270">
+                     <icon
+                      follows="left|top"
+                      height="16"
+                      left="0"
+                      layout="topleft"
+                      name="physics_status_message_icon"
+                      top_pad="0"
+                      width="16" />
+                     <text
+                      follows="left|top"
+                      height="15"
+                      layout="topleft"
+                      left_pad="2"
+                      name="physics_status_message_text"
+                      width="252"
+                      top_delta="3"/>
+                </panel>
         </panel>
       <!-- MODIFIERS PANEL -->
      <panel
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 91adec0789423238f7497250bcca5161b29e0d27..3deb8f723327dd87e3c0a8b1d52036212a6e065b 100755
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -784,14 +784,6 @@
 	<menu_item_separator
 	 layout="topleft"
 	 name="Marketplace Separator" />
-	<menu_item_call
-	 label="Copy to Merchant Outbox"
-	 layout="topleft"
-	 name="Merchant Copy">
-		<menu_item_call.on_click
-		 function="Inventory.DoToSelected"
-		 parameter="copy_to_outbox" />
-	</menu_item_call>
 	<menu_item_call
         label="Copy to Marketplace Listings"
         layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 2463c5f43b79ffdeb1cad7f2b632712631a4dc27..52fcfba79d10c2f88d834242aa4647af0e6c1ccc 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -172,13 +172,6 @@
          name="Buy and Sell L$">
         <menu_item_call.on_click
          function="BuyCurrency" />
-      </menu_item_call>
-      <menu_item_call
-         label="Merchant Outbox..."
-         name="MerchantOutbox">
-        <menu_item_call.on_click
-         function="Floater.ToggleOrBringToFront"
-         parameter="outbox" />
       </menu_item_call>
         <menu_item_call
             label="Marketplace listings..."
diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp
deleted file mode 100755
index bde991a01e873531f0d6588c4a602b7a72247a54..0000000000000000000000000000000000000000
--- a/indra/newview/tests/llcapabilitylistener_test.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * @file   llcapabilitylistener_test.cpp
- * @author Nat Goodspeed
- * @date   2008-12-31
- * @brief  Test for llcapabilitylistener.cpp.
- * 
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "../llviewerprecompiledheaders.h"
-// Own header
-#include "../llcapabilitylistener.h"
-// STL headers
-#include <stdexcept>
-#include <map>
-#include <vector>
-// std headers
-// external library headers
-#include "boost/bind.hpp"
-// other Linden headers
-#include "../test/lltut.h"
-#include "../llcapabilityprovider.h"
-#include "lluuid.h"
-#include "tests/networkio.h"
-#include "tests/commtest.h"
-#include "tests/wrapllerrs.h"
-#include "message.h"
-#include "stringize.h"
-
-#if defined(LL_WINDOWS)
-#pragma warning(disable: 4355)      // using 'this' in base-class ctor initializer expr
-#endif
-
-/*****************************************************************************
-*   TestCapabilityProvider
-*****************************************************************************/
-struct TestCapabilityProvider: public LLCapabilityProvider
-{
-    TestCapabilityProvider(const LLHost& host):
-        mHost(host)
-    {}
-
-    std::string getCapability(const std::string& cap) const
-    {
-        CapMap::const_iterator found = mCaps.find(cap);
-        if (found != mCaps.end())
-            return found->second;
-        // normal LLViewerRegion lookup failure mode
-        return "";
-    }
-    void setCapability(const std::string& cap, const std::string& url)
-    {
-        mCaps[cap] = url;
-    }
-    const LLHost& getHost() const { return mHost; }
-    std::string getDescription() const { return "TestCapabilityProvider"; }
-
-    LLHost mHost;
-    typedef std::map<std::string, std::string> CapMap;
-    CapMap mCaps;
-};
-
-/*****************************************************************************
-*   Dummy LLMessageSystem methods
-*****************************************************************************/
-/*==========================================================================*|
-// This doesn't work because we're already linking in llmessage.a, and we get
-// duplicate-symbol errors from the linker. Perhaps if I wanted to go through
-// the exercise of providing dummy versions of every single symbol defined in
-// message.o -- maybe some day.
-typedef std::vector< std::pair<std::string, std::string> > StringPairVector;
-StringPairVector call_history;
-
-S32 LLMessageSystem::sendReliable(const LLHost& host)
-{
-    call_history.push_back(StringPairVector::value_type("sendReliable", stringize(host)));
-    return 0;
-}
-|*==========================================================================*/
-
-/*****************************************************************************
-*   TUT
-*****************************************************************************/
-namespace tut
-{
-    struct llcapears_data: public commtest_data
-    {
-        TestCapabilityProvider provider;
-        LLCapabilityListener regionListener;
-        LLEventPump& regionPump;
-
-        llcapears_data():
-            provider(host),
-            regionListener("testCapabilityListener", NULL, provider, LLUUID(), LLUUID()),
-            regionPump(regionListener.getCapAPI())
-        {
-            LLCurl::initClass();
-            provider.setCapability("good", server + "capability-test");
-            provider.setCapability("fail", server + "fail");
-        }
-    };
-    typedef test_group<llcapears_data> llcapears_group;
-    typedef llcapears_group::object llcapears_object;
-    llcapears_group llsdmgr("llcapabilitylistener");
-
-    template<> template<>
-    void llcapears_object::test<1>()
-    {
-        LLSD request, body;
-        body["data"] = "yes";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        std::string threw;
-        try
-        {
-            WrapLLErrs capture;
-            regionPump.post(request);
-        }
-        catch (const WrapLLErrs::FatalException& e)
-        {
-            threw = e.what();
-        }
-        ensure_contains("missing capability name", threw, "without 'message' key");
-    }
-
-    template<> template<>
-    void llcapears_object::test<2>()
-    {
-        LLSD request, body;
-        body["data"] = "yes";
-        request["message"] = "good";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        regionPump.post(request);
-        ensure("got response", netio.pump());
-        ensure("success response", success);
-        ensure_equals(result["reply"].asString(), "success");
-
-        body["status"] = 499;
-        body["reason"] = "custom error message";
-        request["message"] = "fail";
-        request["payload"] = body;
-        regionPump.post(request);
-        ensure("got response", netio.pump());
-        ensure("failure response", ! success);
-        ensure_equals(result["status"].asInteger(), body["status"].asInteger());
-        ensure_equals(result["reason"].asString(),  body["reason"].asString());
-    }
-
-    template<> template<>
-    void llcapears_object::test<3>()
-    {
-        LLSD request, body;
-        body["data"] = "yes";
-        request["message"] = "unknown";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        std::string threw;
-        try
-        {
-            WrapLLErrs capture;
-            regionPump.post(request);
-        }
-        catch (const WrapLLErrs::FatalException& e)
-        {
-            threw = e.what();
-        }
-        ensure_contains("bad capability name", threw, "unsupported capability");
-    }
-
-    struct TestMapper: public LLCapabilityListener::CapabilityMapper
-    {
-        // Instantiator gets to specify whether mapper expects a reply.
-        // I'd really like to be able to test CapabilityMapper::buildMessage()
-        // functionality, too, but -- even though LLCapabilityListener accepts
-        // the LLMessageSystem* that it passes to CapabilityMapper --
-        // LLMessageSystem::sendReliable(const LLHost&) isn't virtual, so it's
-        // not helpful to pass a subclass instance. I suspect that making any
-        // LLMessageSystem methods virtual would provoke howls of outrage,
-        // given how heavily it's used. Nor can I just provide a local
-        // definition of LLMessageSystem::sendReliable(const LLHost&) because
-        // we're already linking in the rest of message.o via llmessage.a, and
-        // that produces duplicate-symbol link errors.
-        TestMapper(const std::string& replyMessage = std::string()):
-            LLCapabilityListener::CapabilityMapper("test", replyMessage)
-        {}
-        virtual void buildMessage(LLMessageSystem* msg,
-                                  const LLUUID& agentID,
-                                  const LLUUID& sessionID,
-                                  const std::string& capabilityName,
-                                  const LLSD& payload) const
-        {
-            msg->newMessageFast(_PREHASH_SetStartLocationRequest);
-            msg->nextBlockFast( _PREHASH_AgentData);
-            msg->addUUIDFast(_PREHASH_AgentID, agentID);
-            msg->addUUIDFast(_PREHASH_SessionID, sessionID);
-            msg->nextBlockFast( _PREHASH_StartLocationData);
-            // corrected by sim
-            msg->addStringFast(_PREHASH_SimName, "");
-            msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
-/*==========================================================================*|
-            msg->addVector3Fast(_PREHASH_LocationPos,
-                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
-            msg->addVector3Fast(_PREHASH_LocationLookAt,
-                                ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
-|*==========================================================================*/
-        }
-    };
-
-    template<> template<>
-    void llcapears_object::test<4>()
-    {
-        TestMapper testMapper("WantReply");
-        LLSD request, body;
-        body["data"] = "yes";
-        request["message"] = "test";
-        request["payload"] = body;
-        request["reply"] = replyPump.getName();
-        request["error"] = errorPump.getName();
-        std::string threw;
-        try
-        {
-            WrapLLErrs capture;
-            regionPump.post(request);
-        }
-        catch (const WrapLLErrs::FatalException& e)
-        {
-            threw = e.what();
-        }
-        ensure_contains("capability mapper wants reply", threw, "unimplemented support for reply message");
-    }
-
-    template<> template<>
-    void llcapears_object::test<5>()
-    {
-        TestMapper testMapper;
-        std::string threw;
-        try
-        {
-            TestMapper testMapper2;
-        }
-        catch (const std::runtime_error& e)
-        {
-            threw = e.what();
-        }
-        ensure_contains("no dup cap mapper", threw, "DupCapMapper");
-    }
-}
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 25e6de46d9572b19246f599db643b5363a37d8ff..21c83184dcf9e754f6fcabd18c60f214a047310b 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -234,13 +234,13 @@ void RetryPolicyTestObject::test<6>()
 
 	std::string str1("0");
 	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
+    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str1, seconds_to_wait);
 	ensure("parse 1", success);
 	ensure_equals("parse 1", seconds_to_wait, 0.0);
 
 	std::string str2("999.9");
 	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
+    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str2, seconds_to_wait);
 	ensure("parse 2", success);
 	ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
 
@@ -248,7 +248,7 @@ void RetryPolicyTestObject::test<6>()
 	time(&nowseconds);
 	std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123();
 	seconds_to_wait = F32_MAX;
-	success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+    success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str3, seconds_to_wait);
 	std::cerr << " str3 [" << str3 << "]" << std::endl;
 	ensure("parse 3", success);
 	ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F);
@@ -285,10 +285,10 @@ void RetryPolicyTestObject::test<7>()
 	ensure_approximately_equals_range("header 2", seconds_to_wait, 7.0F, 2.0F);
 
 	LLCore::HttpResponse *response;
-	LLCore::HttpHeaders *headers;
+	LLCore::HttpHeaders::ptr_t headers;
 
 	response = new LLCore::HttpResponse();
-	headers = new LLCore::HttpHeaders();
+	headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
 	response->setStatus(503);
 	response->setHeaders(headers);
 	headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600"));
@@ -299,7 +299,7 @@ void RetryPolicyTestObject::test<7>()
 	response->release();
 
 	response = new LLCore::HttpResponse();
-	headers = new LLCore::HttpHeaders();
+	headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
 	response->setStatus(503);
 	response->setHeaders(headers);
 	time(&nowseconds);
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 6f57daf1519a096c00057ddf7b6020a174d9f952..61120686e4c623df82742e14ef06dad812c093e8 100755
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -106,7 +106,7 @@ const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");
 
 LLSD *gPostRecords = NULL;
 F64   gMinimumInterestLevel = (F64)0.0;
-
+#if 0
 // stubs:
 void LLHTTPClient::post(
 		const std::string& url,
@@ -140,6 +140,7 @@ void LLHTTPClient::post(
 	}
 	responder->successResult(result);
 }
+#endif
 
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
 
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index c49b0350e9b279925145c3674de7861cbd8a9297..ea5014a59c2fa4c07319766567296d7204514a41 100755
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -27,6 +27,7 @@
 #include "linden_common.h"
 
 #include "../test/lltut.h"
+#if 0
 
 #include "../llremoteparcelrequest.h"
 
@@ -134,3 +135,4 @@ namespace tut
 		processor.processParcelInfoReply(gMessageSystem, NULL);
 	}
 }
+#endif
diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp
deleted file mode 100755
index 5e73dbb981dab970d337ea8c46403218079217ec..0000000000000000000000000000000000000000
--- a/indra/newview/tests/lltranslate_test.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/** 
- * @file lltranslate_test.cpp
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "../test/lltut.h"
-#include "../lltranslate.h"
-#include "../llversioninfo.h"
-#include "../llviewercontrol.h"
-
-#include "llbufferstream.h"
-#include "lltrans.h"
-#include "llui.h"
-
-#include "../../llmessage/llhttpconstants.cpp"
-
-static const std::string GOOGLE_VALID_RESPONSE1 =
-"{\
- \"data\": {\
-  \"translations\": [\
-   {\
-    \"translatedText\": \"привет\",\
-    \"detectedSourceLanguage\": \"es\"\
-   }\
-  ]\
- }\
-}";
-
-static const std::string GOOGLE_VALID_RESPONSE2 =
-"{\
- \"data\": {\
-  \"translations\": [\
-   {\
-    \"translatedText\": \"привет\"\
-   }\
-  ]\
- }\
-}\
-";
-
-static const std::string GOOGLE_VALID_RESPONSE3 =
-"{\
- \"error\": {\
-  \"errors\": [\
-   {\
-    \"domain\": \"global\",\
-    \"reason\": \"invalid\",\
-    \"message\": \"Invalid Value\"\
-   }\
-  ],\
-  \"code\": 400,\
-  \"message\": \"Invalid Value\"\
- }\
-}";
-
-static const std::string BING_VALID_RESPONSE1 =
-"<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Привет</string>";
-
-static const std::string BING_VALID_RESPONSE2 =
-"<html><body><h1>Argument Exception</h1><p>Method: Translate()</p><p>Parameter: </p>\
-<p>Message: 'from' must be a valid language</p><code></code>\
-<p>message id=3743.V2_Rest.Translate.58E8454F</p></body></html>";
-
-static const std::string BING_VALID_RESPONSE3 =
-"<html><body><h1>Argument Exception</h1><p>Method: Translate()</p>\
-<p>Parameter: appId</p><p>Message: Invalid appId&#xD;\nParameter name: appId</p>\
-<code></code><p>message id=3737.V2_Rest.Translate.56016759</p></body></html>";
-
-namespace tut
-{
-	class translate_test
-	{
-	protected:
-		void test_translation(
-			LLTranslationAPIHandler& handler,
-			int status, const std::string& resp,
-			const std::string& exp_trans, const std::string& exp_lang, const std::string& exp_err)
-		{
-			std::string translation, detected_lang, err_msg;
-			bool rc = handler.parseResponse(status, resp, translation, detected_lang, err_msg);
-			ensure_equals("rc", rc, (status == 200));
-			ensure_equals("err_msg", err_msg, exp_err);
-			ensure_equals("translation", translation, exp_trans);
-			ensure_equals("detected_lang", detected_lang,  exp_lang);
-		}
-
-		LLGoogleTranslationHandler mGoogle;
-		LLBingTranslationHandler mBing;
-	};
-
-	typedef test_group<translate_test> translate_test_group_t;
-	typedef translate_test_group_t::object translate_test_object_t;
-	tut::translate_test_group_t tut_translate("LLTranslate");
-
-	template<> template<>
-	void translate_test_object_t::test<1>()
-	{
-		test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE1, "привет", "es", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<2>()
-	{
-		test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE2, "привет", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<3>()
-	{
-		test_translation(mGoogle, 400, GOOGLE_VALID_RESPONSE3, "", "", "Invalid Value");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<4>()
-	{
-		test_translation(mGoogle, 400,
-			"",
-			"", "", "* Line 1, Column 1\n  Syntax error: value, object or array expected.\n");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<5>()
-	{
-		test_translation(mGoogle, 400,
-			"[]",
-			"", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<6>()
-	{
-		test_translation(mGoogle, 400,
-			"{\"oops\": \"invalid\"}",
-			"", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<7>()
-	{
-		test_translation(mGoogle, 400,
-			"{\"data\": {}}",
-			"", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<8>()
-	{
-		test_translation(mGoogle, 400,
-				"{\"data\": { \"translations\": [ {} ] }}",
-			"", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<9>()
-	{
-		test_translation(mGoogle, 400,
-				"{\"data\": { \"translations\": [ { \"translatedTextZZZ\": \"привет\", \"detectedSourceLanguageZZZ\": \"es\" } ] }}",
-			"", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<10>()
-	{
-		test_translation(mBing, 200, BING_VALID_RESPONSE1, "Привет", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<11>()
-	{
-		test_translation(mBing, 400, BING_VALID_RESPONSE2, "", "", "'from' must be a valid language");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<12>()
-	{
-		test_translation(mBing, 400, BING_VALID_RESPONSE3, "", "", "Invalid appId\nParameter name: appId");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<13>()
-	{
-		test_translation(mBing, 200,
-			"Привет</string>",
-			"Привет", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<14>()
-	{
-		test_translation(mBing, 200,
-			"<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Привет",
-			"Привет", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<15>()
-	{
-		test_translation(mBing, 200,
-			"Привет",
-			"Привет", "", "");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<16>()
-	{
-		test_translation(mBing, 400,
-			"Message: some error</p>",
-			"", "", "some error");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<17>()
-	{
-		test_translation(mBing, 400,
-			"Message: some error",
-			"", "", "some error");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<18>()
-	{
-		test_translation(mBing, 400,
-			"some error</p>",
-			"", "", "some error");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<19>()
-	{
-		test_translation(mBing, 400,
-			"some error",
-			"", "", "some error");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<20>()
-	{
-		std::string url;
-		mBing.getTranslateURL(url, "en", "es", "hi");
-		ensure_equals("bing URL", url,
-			"http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es&from=en");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<21>()
-	{
-		std::string url;
-		mBing.getTranslateURL(url, "", "es", "hi");
-		ensure_equals("bing URL", url,
-			"http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<22>()
-	{
-		std::string url;
-		mGoogle.getTranslateURL(url, "en", "es", "hi");
-		ensure_equals("google URL", url,
-			"https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es&source=en");
-	}
-
-	template<> template<>
-	void translate_test_object_t::test<23>()
-	{
-		std::string url;
-		mGoogle.getTranslateURL(url, "", "es", "hi");
-		ensure_equals("google URL", url,
-			"https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es");
-	}
-}
-
-//== Misc stubs ===============================================================
-LLControlGroup gSavedSettings("test");
-
-std::string LLUI::getLanguage() { return "en"; }
-std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return "dummy"; }
-
-LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {}
-std::string LLControlGroup::getString(const std::string& name) { return "dummy"; }
-LLControlGroup::~LLControlGroup() {}
-
-LLCurl::Responder::Responder() {}
-void LLCurl::Responder::httpFailure() { }
-void LLCurl::Responder::httpSuccess() { }
-void LLCurl::Responder::httpCompleted() { }
-void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
-LLCurl::Responder::~Responder() {}
-
-void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32, bool) {}
-void LLHTTPClient::get(const std::string&, LLPointer<LLCurl::Responder>, const LLSD&, const F32, bool) {}
-
-LLBufferStream::LLBufferStream(const LLChannelDescriptors& channels, LLBufferArray* buffer)
-:	std::iostream(&mStreamBuf), mStreamBuf(channels, buffer) {}
-LLBufferStream::~LLBufferStream() {}
-
-LLBufferStreamBuf::LLBufferStreamBuf(const LLChannelDescriptors&, LLBufferArray*) {}
-#if( LL_WINDOWS || __GNUC__ > 2)
-LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff(
-	off_type off,
-	std::ios::seekdir way,
-	std::ios::openmode which)
-#else
-streampos LLBufferStreamBuf::seekoff(
-	streamoff off,
-	std::ios::seekdir way,
-	std::ios::openmode which)
-#endif
-{ return 0; }
-int LLBufferStreamBuf::sync() {return 0;}
-int LLBufferStreamBuf::underflow() {return 0;}
-int LLBufferStreamBuf::overflow(int) {return 0;}
-LLBufferStreamBuf::~LLBufferStreamBuf() {}
-
-S32 LLVersionInfo::getBuild() { return 0; }
-const std::string& LLVersionInfo::getChannel() {static std::string dummy; return dummy;}
-S32 LLVersionInfo::getMajor() { return 0; }
-S32 LLVersionInfo::getMinor() { return 0; }
-S32 LLVersionInfo::getPatch() { return 0; }
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 01d1d830a26f129ff1a135821c7bef5ce671f507..229cb8e5a0abd13a7660d7f210d9fd5222845aae 100755
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -4,6 +4,7 @@ project (lltest)
 
 include(00-Common)
 include(LLCommon)
+include(LLCoreHttp)
 include(LLInventory)
 include(LLMath)
 include(LLMessage)
@@ -18,6 +19,7 @@ include(GoogleMock)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLDATABASE_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
     ${LLMESSAGE_INCLUDE_DIRS}
@@ -91,12 +93,16 @@ target_link_libraries(lltest
     ${LLXML_LIBRARIES}
     ${LSCRIPT_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${EXPAT_LIBRARIES}
     ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
     ${BOOST_REGEX_LIBRARY}
+    ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_SYSTEM_LIBRARY}
     ${DL_LIBRARY}
     ${GOOGLE_PERFTOOLS_LIBRARIES}
     )
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index 97726c2b929d31b43bebf29cd735b8fe830fd52a..ff900ab96bea3840cf497417a7a4114007920597 100755
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -41,8 +41,6 @@
 #include "llpipeutil.h"
 #include "llpumpio.h"
 #include "llsd.h"
-#include "llsdrpcclient.h"
-#include "llsdrpcserver.h"
 #include "llsdserialize.h"
 #include "llcommon.h"
 #include "lluuid.h"
@@ -1177,425 +1175,6 @@ namespace tut
 	}
 }
 
-namespace tut
-{
-	struct rpc_server_data
-	{
-		class LLSimpleRPCResponse : public LLSDRPCResponse
-		{
-		public:
-			LLSimpleRPCResponse(LLSD* response) :
-				mResponsePtr(response)
-			{
-			}
-			~LLSimpleRPCResponse() 
-			{
-			}
-			virtual bool response(LLPumpIO* pump)
-			{
-				*mResponsePtr = mReturnValue;
-				return true;
-			}
-			virtual bool fault(LLPumpIO* pump)
-			{
-				*mResponsePtr = mReturnValue;
-				return false;
-			}
-			virtual bool error(LLPumpIO* pump)
-			{
-				ensure("LLSimpleRPCResponse::error()", false);
-				return false;
-			}
-		public:
-			LLSD* mResponsePtr;
-		};
-
-		class LLSimpleRPCClient : public LLSDRPCClient
-		{
-		public:
-			LLSimpleRPCClient(LLSD* response) :
-				mResponsePtr(response)
-			{
-			}
-			~LLSimpleRPCClient() {}
-			void echo(const LLSD& parameter)
-			{
-				LLSimpleRPCResponse* resp;
-				resp = new LLSimpleRPCResponse(mResponsePtr);
-				static const std::string URI_NONE;
-				static const std::string METHOD_ECHO("echo");
-				call(URI_NONE, METHOD_ECHO, parameter, resp, EPBQ_CALLBACK);
-			}
-		public:
-			LLSD* mResponsePtr;
-		};
-
-		class LLSimpleRPCServer : public LLSDRPCServer
-		{
-		public:
-			LLSimpleRPCServer()
-			{
-				mMethods["echo"] = new mem_fn_t(
-					this,
-					&LLSimpleRPCServer::rpc_Echo);
-			}
-			~LLSimpleRPCServer() {}
-		protected:
-			typedef LLSDRPCMethodCall<LLSimpleRPCServer> mem_fn_t;
-			ESDRPCSStatus rpc_Echo(
-				const LLSD& parameter,
-				const LLChannelDescriptors& channels,
-				LLBufferArray* data)
-			{
-				buildResponse(channels, data, parameter);
-				return ESDRPCS_DONE;
-			}
-		};
-
-		apr_pool_t* mPool;
-		LLPumpIO* mPump;
-		LLPumpIO::chain_t mChain;
-		LLSimpleRPCClient* mClient;
-		LLSD mResponse;
-
-		rpc_server_data() :
-			mPool(NULL),
-			mPump(NULL),
-			mClient(NULL)
-		{
-			apr_pool_create(&mPool, NULL);
-			mPump = new LLPumpIO(mPool);
-			mClient = new LLSimpleRPCClient(&mResponse);
-			mChain.push_back(LLIOPipe::ptr_t(mClient));
-			mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest));
-			mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
-			mChain.push_back(LLIOPipe::ptr_t(new LLSimpleRPCServer));
-			mChain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
-			mChain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
-			mChain.push_back(LLIOPipe::ptr_t(mClient));
-		}
-		~rpc_server_data()
-		{
-			mChain.clear();
-			delete mPump;
-			mPump = NULL;
-			apr_pool_destroy(mPool);
-			mPool = NULL;
-		}
-		void pump_loop(const LLSD& request)
-		{
-			LLTimer timer;
-			timer.setTimerExpirySec(1.0f);
-			mClient->echo(request);
-			mPump->addChain(mChain, DEFAULT_CHAIN_EXPIRY_SECS);
-			while(mResponse.isUndefined() && !timer.hasExpired())
-			{
-				mPump->pump();
-				mPump->callback();
-			}
-		}
-	};
-	typedef test_group<rpc_server_data> rpc_server_test;
-	typedef rpc_server_test::object rpc_server_object;
-	tut::rpc_server_test rpc("rpc_server");
-
-	template<> template<>
-	void rpc_server_object::test<1>()
-	{
-		LLSD request;
-		request = 1;
-		pump_loop(request);
-		//LL_INFOS() << "request: " << *request << LL_ENDL;
-		//LL_INFOS() << "response: " << *mResponse << LL_ENDL;
-		ensure_equals("integer request response", mResponse.asInteger(), 1);
-	}
-
-	template<> template<>
-	void rpc_server_object::test<2>()
-	{
-//#if LL_WINDOWS && _MSC_VER >= 1400
-//        skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
-//#endif
-		std::string uri("sl-am:66.150.244.180:12035/location?start=region&px=70.9247&py=254.378&pz=38.7304&lx=-0.043753&ly=-0.999042&lz=0");
-		std::stringstream stream;
-		stream << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
-		std::vector<U8> expected_binary;
-		expected_binary.resize(stream.str().size());
-		memcpy(&expected_binary[0], stream.str().c_str(), stream.str().size());		/* Flawfinder: ignore */
-		stream.str("");
-		stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
-				  << "{'agent_id':'3c115e51-04f4-523c-9fa6-98aff1034730', 'session_id':'2c585cec-038c-40b0-b42e-a25ebab4d132', 'circuit_code':i1075, 'start':'region', 'limited_to_estate':i1 'first_name':'Phoenix', 'last_name':'Linden', 'group_title':'', 'group_id':u00000000-0000-0000-0000-000000000000, 'position':[r70.9247,r254.378,r38.7304], 'look_at':[r-0.043753,r-0.999042,r0], 'granters':[ua2e76fcd-9360-4f6d-a924-000000000003], 'texture_data':['5e481e8a-58a6-fc34-6e61-c7a36095c07f', 'c39675f5-ca90-a304-bb31-42cdb803a132', '5c989edf-88d1-b2ac-b00b-5ed4bab8e368', '6522e74d-1660-4e7f-b601-6f48c1659a77', '7ca39b4c-bd19-4699-aff7-f93fd03d3e7b', '41c58177-5eb6-5aeb-029d-bc4093f3c130', '97b75473-8b93-9b25-2a11-035b9ae93195', '1c2d8d9b-90eb-89d4-dea8-c1ed83990614', '69ec543f-e27b-c07c-9094-a8be6300f274', 'c9f8b80f-c629-4633-04ee-c566ce9fea4b', '989cddba-7ab6-01ed-67aa-74accd2a2a65', '45e319b2-6a8c-fa5c-895b-1a7149b88aef', '5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', '406f98fd-9c89-1d52-5f39-e67d508c5ee5', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'], "
-				  << "'attachment_data':["
-				  << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},"
-				  << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << expected_binary.size() << ")\"";
-		stream.write((const char*)&expected_binary[0], expected_binary.size());
-		stream << "\"}"
-				  << "]"
-				  << "}]";
-
-		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(
-			request,
-			stream,
-			stream.str().size());
-		ensure("parsed something", (count > 0));
-
-		pump_loop(request);
-		ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
-		ensure_equals("return size", mResponse.size(), 3);
-
-		ensure_equals(
-			"uri parameter type",
-			mResponse[0].type(),
-			LLSD::TypeMap);
-		ensure_equals(
-			"uri type",
-			mResponse[0]["uri"].type(),
-			LLSD::TypeString);
-		ensure_equals("uri value", mResponse[0]["uri"].asString(), uri);
-
-		ensure_equals(
-			"version parameter type",
-			mResponse[1].type(),
-			LLSD::TypeMap);
-		ensure_equals(
-			"version type",
-			mResponse[1]["version"].type(),
-			LLSD::TypeInteger);
-		ensure_equals(
-			"version value",
-			mResponse[1]["version"].asInteger(),
-			1);
-
-		ensure_equals("agent params type", mResponse[2].type(), LLSD::TypeMap);
-		LLSD attachment_data = mResponse[2]["attachment_data"];
-		ensure("attachment data exists", attachment_data.isDefined());
-		ensure_equals(
-			"attachment type",
-			attachment_data.type(),
-			LLSD::TypeArray);
-		ensure_equals(
-			"attachment type 0",
-			attachment_data[0].type(),
-			LLSD::TypeMap);
-		ensure_equals(
-			"attachment type 1",
-			attachment_data[1].type(),
-			LLSD::TypeMap);
-		ensure_equals("attachment size 1", attachment_data[1].size(), 3);
-		ensure_equals(
-			"asset data type",
-			attachment_data[1]["asset_data"].type(),
-			LLSD::TypeBinary);
-		std::vector<U8> actual_binary;
-		actual_binary = attachment_data[1]["asset_data"].asBinary();
-		ensure_equals(
-			"binary data size",
-			actual_binary.size(),
-			expected_binary.size());
-		ensure(
-			"binary data",
-			(0 == memcmp(
-				&actual_binary[0],
-				&expected_binary[0],
-				expected_binary.size())));
-	}
-
-	template<> template<>
-	void rpc_server_object::test<3>()
-	{
-//#if LL_WINDOWS && _MSC_VER >= 1400
-//        skip_fail("Fails on VS2005 due to broken LLSDSerialize::fromNotation() parser.");
-//#endif
-		std::string uri("sl-am:66.150.244.180:12035/location?start=region&px=70.9247&py=254.378&pz=38.7304&lx=-0.043753&ly=-0.999042&lz=0");
-
-		LLBufferArray buffer;
-		LLChannelDescriptors buffer_channels = buffer.nextChannel();
-		LLBufferStream stream(buffer_channels, &buffer);
-		stream << "[{'uri':'" << uri << "'}, {'version':i1}, "
-				  << "{'agent_id':'3c115e51-04f4-523c-9fa6-98aff1034730', 'session_id':'2c585cec-038c-40b0-b42e-a25ebab4d132', 'circuit_code':i1075, 'start':'region', 'limited_to_estate':i1 'first_name':'Phoenix', 'last_name':'Linden', 'group_title':'', 'group_id':u00000000-0000-0000-0000-000000000000, 'position':[r70.9247,r254.378,r38.7304], 'look_at':[r-0.043753,r-0.999042,r0], 'granters':[ua2e76fcd-9360-4f6d-a924-000000000003], 'texture_data':['5e481e8a-58a6-fc34-6e61-c7a36095c07f', 'c39675f5-ca90-a304-bb31-42cdb803a132', '5c989edf-88d1-b2ac-b00b-5ed4bab8e368', '6522e74d-1660-4e7f-b601-6f48c1659a77', '7ca39b4c-bd19-4699-aff7-f93fd03d3e7b', '41c58177-5eb6-5aeb-029d-bc4093f3c130', '97b75473-8b93-9b25-2a11-035b9ae93195', '1c2d8d9b-90eb-89d4-dea8-c1ed83990614', '69ec543f-e27b-c07c-9094-a8be6300f274', 'c9f8b80f-c629-4633-04ee-c566ce9fea4b', '989cddba-7ab6-01ed-67aa-74accd2a2a65', '45e319b2-6a8c-fa5c-895b-1a7149b88aef', '5748decc-f629-461c-9a36-a35a221fe21f', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', '406f98fd-9c89-1d52-5f39-e67d508c5ee5', '685fbe10-ab40-f065-0aec-726cc6dfd7a1', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97', 'c228d1cf-4b5d-4ba8-84f4-899a0796aa97'], "
-				  << "'attachment_data':["
-				  << "{'attachment_point':i2, 'item_id':'d6852c11-a74e-309a-0462-50533f1ef9b3', 'asset_id':'c69b29b1-8944-58ae-a7c5-2ca7b23e22fb'},";
-
-		std::stringstream tmp_str;
-		tmp_str << "{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n}";
-		std::vector<U8> expected_binary;
-		expected_binary.resize(tmp_str.str().size());
-		memcpy(		/* Flawfinder: ignore */
-			&expected_binary[0],
-			tmp_str.str().c_str(),
-			tmp_str.str().size());
-
-		LLBufferArray attachment_buffer;
-		LLChannelDescriptors attach_channels = attachment_buffer.nextChannel();
-		LLBufferStream attach_stream(attach_channels, &attachment_buffer);
-		attach_stream.write((const char*)&expected_binary[0], expected_binary.size());
-		attach_stream.flush();
-		S32 len = attachment_buffer.countAfter(attach_channels.out(), NULL);
-		stream << "{'attachment_point':i10, 'item_id':'ff852c22-a74e-309a-0462-50533f1ef900', 'asset_data':b(" << len << ")\"";
-		stream.flush();
-		buffer.takeContents(attachment_buffer);
-		stream << "\"}]}]";
-		stream.flush();
-
-		LLChannelDescriptors read_channel = buffer.nextChannel();
-		LLBufferStream read_stream(read_channel, &buffer);
-		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(
-			request,
-			read_stream,
-			buffer.count(read_channel.in()));
-		ensure("parsed something", (count > 0));
-		ensure("deserialized", request.isDefined());
-
-		// do the rpc round trip
-		pump_loop(request);
-
-		ensure_equals("return type", mResponse.type(), LLSD::TypeArray);
-		ensure_equals("return size", mResponse.size(), 3);
-
-		LLSD child = mResponse[0];
-		ensure("uri map exists", child.isDefined());
-		ensure_equals("uri parameter type", child.type(), LLSD::TypeMap);
-		ensure("uri string exists", child.has("uri"));
-		ensure_equals("uri type", child["uri"].type(), LLSD::TypeString);
-		ensure_equals("uri value", child["uri"].asString(), uri);
-
-		child = mResponse[1];
-		ensure("version map exists",	child.isDefined());
-		ensure_equals("version param type", child.type(), LLSD::TypeMap);
-		ensure_equals(
-			"version type",
-			child["version"].type(),
-			LLSD::TypeInteger);
-		ensure_equals("version value", child["version"].asInteger(), 1);
-
-		child = mResponse[2];
-		ensure("agent params map exists", child.isDefined());
-		ensure_equals("agent params type", child.type(), LLSD::TypeMap);
-		child = child["attachment_data"];
-		ensure("attachment data exists", child.isDefined());
-		ensure_equals("attachment type", child.type(), LLSD::TypeArray);
-		LLSD attachment = child[0];
-		ensure_equals("attachment type 0", attachment.type(), LLSD::TypeMap);
-		attachment = child[1];
-		ensure_equals("attachment type 1", attachment.type(), LLSD::TypeMap);
-		ensure_equals("attachment size 1", attachment.size(), 3);
-		ensure_equals(
-			"asset data type",
-			attachment["asset_data"].type(),
-			LLSD::TypeBinary);
-		std::vector<U8> actual_binary = attachment["asset_data"].asBinary();
-		ensure_equals(
-			"binary data size",
-			actual_binary.size(),
-			expected_binary.size());
-		ensure(
-			"binary data",
-			(0 == memcmp(
-				&actual_binary[0],
-				&expected_binary[0],
-				expected_binary.size())));
-	}
-
-	template<> template<>
-	void rpc_server_object::test<4>()
-	{
-		std::string message("parcel '' is naughty.");
-		std::stringstream str;
-		str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
-			<< "'}";
-		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(
-			request,
-			str,
-			str.str().size());
-		ensure_equals("parse count", count, 2);
-		ensure_equals("request type", request.type(), LLSD::TypeMap);
-		pump_loop(request);
-		ensure("valid response", mResponse.isDefined());
-		ensure_equals("response type", mResponse.type(), LLSD::TypeMap);
-		std::string actual = mResponse["message"].asString();
-		ensure_equals("message contents", actual, message);
-	}
-
-	template<> template<>
-	void rpc_server_object::test<5>()
-	{
-		// test some of the problem cases with llsdrpc over xmlrpc -
-		// for example:
-		// * arrays are auto-converted to parameter lists, thus, this
-		// becomes one parameter.
-		// * undef goes over the wire as false (this might not be a good idea)
-		// * uuids are converted to string.
-		std::string val = "[{'failures':!,'successfuls':[u3c115e51-04f4-523c-9fa6-98aff1034730]}]";
-		std::istringstream istr;
-		istr.str(val);
-		LLSD sd;
-		LLSDSerialize::fromNotation(sd, istr, val.size());
-		pump_loop(sd);
-		ensure("valid response", mResponse.isDefined());
-		ensure_equals("parsed type", mResponse.type(), LLSD::TypeMap);
-		ensure_equals("parsed size", mResponse.size(), 2);
-		LLSD failures = mResponse["failures"];
-		ensure_equals("no failures.", failures.asBoolean(), false);
-		LLSD success = mResponse["successfuls"];
-		ensure_equals("success type", success.type(), LLSD::TypeArray);
-		ensure_equals("success size", success.size(), 1);
-		ensure_equals(
-			"success instance type",
-			success[0].type(),
-			LLSD::TypeString);
-	}
-
-/*
-	template<> template<>
-	void rpc_server_object::test<5>()
-	{
-		std::string expected("\xf3");//\xffsomething");
-		LLSD* request = LLSD::createString(expected);
-		pump_loop(request);
-		std::string actual;
-		mResponse->getString(actual);
-		if(actual != expected)
-		{
-			//LL_WARNS() << "iteration " << i << LL_ENDL;
-			std::ostringstream e_str;
-			std::string::iterator iter = expected.begin();
-			std::string::iterator end = expected.end();
-			for(; iter != end; ++iter)
-			{
-				e_str << (S32)((U8)(*iter)) << " ";
-			}
-			e_str << std::endl;
-			llsd_serialize_string(e_str, expected);
-			LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
-			LL_WARNS() << "expected:	  " << e_str.str() << LL_ENDL;
-
-			std::ostringstream a_str;
-			iter = actual.begin();
-			end = actual.end();
-			for(; iter != end; ++iter)
-			{
-				a_str << (S32)((U8)(*iter)) << " ";
-			}
-			a_str << std::endl;
-			llsd_serialize_string(a_str, actual);
-			LL_WARNS() << "actual size:	  " << actual.size() << LL_ENDL;
-			LL_WARNS() << "actual:		" << a_str.str() << LL_ENDL;
-		}
-		ensure_equals("binary string request response", actual, expected);
-		delete request;
-	}
-
-	template<> template<>
-	void rpc_server_object::test<5>()
-	{
-	}
-*/
-}
-
-
 /*
 'asset_data':b(12100)"{'task_id':ucc706f2d-0b68-68f8-11a4-f1043ff35ca0}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444921\n\ttotal_crc\t323\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.368634403\t0.00781063363\t-0.569040775\n\toldpos\t150.117996\t25.8658009\t8.19664001\n\trotation\t-0.06293071806430816650390625\t-0.6995697021484375\t-0.7002241611480712890625\t0.1277817934751510620117188\n\tchildpos\t-0.00499999989\t-0.0359999985\t0.307999998\n\tchildrot\t-0.515492737293243408203125\t-0.46601200103759765625\t0.529055416584014892578125\t0.4870323240756988525390625\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061088050622956\n\treztime\t1094866329019785\n\tparceltime\t1133568981980596\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':u61fa7364-e151-0597-774c-523312dae31b}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444922\n\ttotal_crc\t324\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.367110789\t0.00780026987\t-0.566269755\n\toldpos\t150.115005\t25.8479004\t8.18669987\n\trotation\t0.47332942485809326171875\t-0.380102097988128662109375\t-0.5734078884124755859375\t0.550168216228485107421875\n\tchildpos\t-0.00499999989\t-0.0370000005\t0.305000007\n\tchildrot\t-0.736649334430694580078125\t-0.03042060509324073791503906\t-0.02784589119255542755126953\t0.67501628398895263671875\n\tscale\t0.074629\t0.289956\t0.01\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t16\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\tscale_x\t1\n\t\t\tscale_y\t1\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t1\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t6\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tf54a0c32-3cd1-d49a-5b4f-7b792bebc204\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\tddde1ffc-678b-3cda-1748-513086bdf01b\n\t\tcolors\t0.937255 0.796078 0.494118 1\n\t\tscales\t1\n\t\tscalet\t-1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t0\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087839248891\n\treztime\t1094866329020800\n\tparceltime\t1133568981981983\n\ttax_rate\t1.00084\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ub8d68643-7dd8-57af-0d24-8790032aed0c}\n{\n\tname\tObject|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444923\n\ttotal_crc\t235\n\ttype\t2\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.120029509\t-0.00284469454\t-0.0302077383\n\toldpos\t150.710999\t25.8584995\t8.19172001\n\trotation\t0.145459949970245361328125\t-0.1646589934825897216796875\t0.659558117389678955078125\t-0.718826770782470703125\n\tchildpos\t0\t-0.182999998\t-0.26699999\n\tchildrot\t0.991444766521453857421875\t3.271923924330621957778931e-05\t-0.0002416197530692443251609802\t0.1305266767740249633789062\n\tscale\t0.0382982\t0.205957\t0.368276\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087534454174\n\treztime\t1094866329021741\n\tparceltime\t1133568981982889\n\ttax_rate\t1.00326\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tchild\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n{'task_id':ue4b19200-9d33-962f-c8c5-6f25be3a3fd0}\n{\n\tname\tApotheosis_Immolaine_tail|\n\tpermissions 0\n\t{\n\t\tbase_mask\t7fffffff\n\t\towner_mask\t7fffffff\n\t\tgroup_mask\t00000000\n\t\teveryone_mask\t00000000\n\t\tnext_owner_mask\t7fffffff\n\t\tcreator_id\t13fd9595-a47b-4d64-a5fb-6da645f038e0\n\t\towner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tlast_owner_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\t\tgroup_id\t00000000-0000-0000-0000-000000000000\n\t}\n\tlocal_id\t217444924\n\ttotal_crc\t675\n\ttype\t1\n\ttask_valid\t2\n\ttravel_access\t13\n\tdisplayopts\t2\n\tdisplaytype\tv\n\tpos\t-0.34780401\t-0.00968400016\t-0.260098994\n\toldpos\t0\t0\t0\n\trotation\t0.73164522647857666015625\t-0.67541944980621337890625\t-0.07733880728483200073242188\t0.05022468417882919311523438\n\tvelocity\t0\t0\t0\n\tangvel\t0\t0\t0\n\tscale\t0.0382982\t0.32228\t0.383834\n\tsit_offset\t0\t0\t0\n\tcamera_eye_offset\t0\t0\t0\n\tcamera_at_offset\t0\t0\t0\n\tsit_quat\t0\t0\t0\t1\n\tsit_hint\t0\n\tstate\t160\n\tmaterial\t3\n\tsoundid\t00000000-0000-0000-0000-000000000000\n\tsoundgain\t0\n\tsoundradius\t0\n\tsoundflags\t0\n\ttextcolor\t0 0 0 1\n\tselected\t0\n\tselector\t00000000-0000-0000-0000-000000000000\n\tusephysics\t0\n\trotate_x\t1\n\trotate_y\t1\n\trotate_z\t1\n\tphantom\t0\n\tremote_script_access_pin\t0\n\tvolume_detect\t0\n\tblock_grabs\t0\n\tdie_at_edge\t0\n\treturn_at_edge\t0\n\ttemporary\t0\n\tsandbox\t0\n\tsandboxhome\t0\t0\t0\n\tshape 0\n\t{\n\t\tpath 0\n\t\t{\n\t\t\tcurve\t32\n\t\t\tbegin\t0.3\n\t\t\tend\t0.65\n\t\t\tscale_x\t1\n\t\t\tscale_y\t0.05\n\t\t\tshear_x\t0\n\t\t\tshear_y\t0\n\t\t\ttwist\t0\n\t\t\ttwist_begin\t0\n\t\t\tradius_offset\t0\n\t\t\ttaper_x\t0\n\t\t\ttaper_y\t0\n\t\t\trevolutions\t1\n\t\t\tskew\t0\n\t\t}\n\t\tprofile 0\n\t\t{\n\t\t\tcurve\t0\n\t\t\tbegin\t0\n\t\t\tend\t1\n\t\t\thollow\t0\n\t\t}\n\t}\n\tfaces\t3\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\t{\n\t\timageid\te7150bed-3e3e-c698-eb15-d17b178148af\n\t\tcolors\t0.843137 0.156863 0.156863 1\n\t\tscales\t15\n\t\tscalet\t1\n\t\toffsets\t0\n\t\toffsett\t0\n\t\timagerot\t-1.57084\n\t\tbump\t0\n\t\tfullbright\t0\n\t\tmedia_flags\t0\n\t}\n\tps_next_crc\t1\n\tgpw_bias\t1\n\tip\t0\n\tcomplete\tTRUE\n\tdelay\t50000\n\tnextstart\t0\n\tbirthtime\t1061087463950186\n\treztime\t1094866329022555\n\tparceltime\t1133568981984359\n\tdescription\t(No Description)|\n\ttax_rate\t1.01736\n\tnamevalue\tAttachPt U32 RW S 10\n\tnamevalue\tAttachmentOrientation VEC3 RW DS -3.110088, -0.182018, 1.493795\n\tnamevalue\tAttachmentOffset VEC3 RW DS -0.347804, -0.009684, -0.260099\n\tnamevalue\tAttachItemID STRING RW SV 20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tscratchpad\t0\n\t{\n\t\n\t}\n\tsale_info\t0\n\t{\n\t\tsale_type\tnot\n\t\tsale_price\t10\n\t}\n\torig_asset_id\t8747acbc-d391-1e59-69f1-41d06830e6c0\n\torig_item_id\t20f36c3a-b44b-9bc7-87f3-018bfdfc8cda\n\tfrom_task_id\t3c115e51-04f4-523c-9fa6-98aff1034730\n\tcorrect_family_id\t00000000-0000-0000-0000-000000000000\n\thas_rezzed\t0\n\tpre_link_base_mask\t7fffffff\n\tlinked \tlinked\n\tdefault_pay_price\t-2\t1\t5\t10\t20\n}\n"
 */
diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp
index aa23699de07298dedd615cd8b5c1e60b6f216205..8718360f0cb309caf0ad93f477348a4a1433f74b 100755
--- a/indra/test/message_tut.cpp
+++ b/indra/test/message_tut.cpp
@@ -28,7 +28,7 @@
 #include <tut/tut.hpp>
 #include "linden_common.h"
 #include "lltut.h"
-
+#include "llhttpconstants.h"
 #include "llapr.h"
 #include "llmessageconfig.h"
 #include "llsdserialize.h"
diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt
index c152f7c0a69627a34b895713084f079c6dd9a3e7..3bedeb7292ff310cea76b22fd6bd5cfe220e9f8d 100755
--- a/indra/viewer_components/login/CMakeLists.txt
+++ b/indra/viewer_components/login/CMakeLists.txt
@@ -10,6 +10,8 @@ include(LLCommon)
 include(LLMath)
 include(LLXML)
 include(Boost)
+include(LLCoreHttp)
+include(LLMessage)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -42,12 +44,14 @@ add_library(lllogin
             )
 
 target_link_libraries(lllogin
+    ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
     ${LLMATH_LIBRARIES}
     ${LLXML_LIBRARIES}
-    ${BOOST_CONTEXT_LIBRARY}
     ${BOOST_THREAD_LIBRARY}
     ${BOOST_COROUTINE_LIBRARY}
+    ${BOOST_CONTEXT_LIBRARY}
     ${BOOST_SYSTEM_LIBRARY}
     )
 
@@ -58,7 +62,7 @@ if(LL_TESTS)
   set_source_files_properties(
     lllogin.cpp
     PROPERTIES
-    LL_TEST_ADDITIONAL_LIBRARIES "${BOOST_COROUTINE_LIBRARY};${BOOST_CONTEXT_LIBRARY};${BOOST_THREAD_LIBRARY};${BOOST_SYSTEM_LIBRARY}"
+    LL_TEST_ADDITIONAL_LIBRARIES "${LLMESSAGE_LIBRARIES};${LLCOREHTTP_LIBRARIES};${LLCOMMON_LIBRARIES};${BOOST_COROUTINE_LIBRARY};${BOOST_CONTEXT_LIBRARY};${BOOST_THREAD_LIBRARY};${BOOST_SYSTEM_LIBRARY}"
     )
 
   LL_ADD_PROJECT_UNIT_TESTS(lllogin "${lllogin_TEST_SOURCE_FILES}")
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index b8408a6fb45bf5ec771382ffc376eff823c534b2..53d4acc9e0157ce76165ba54400aa94247254166 100755
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -107,9 +107,8 @@ class LLLogin::Impl
     }
 
     // In a coroutine's top-level function args, do NOT NOT NOT accept
-    // references (const or otherwise) to anything but the self argument! Pass
-    // by value only!
-    void login_(LLCoros::self& self, std::string uri, LLSD credentials);
+    // references (const or otherwise) to anything! Pass by value only!
+    void loginCoro(std::string uri, LLSD credentials);
 
     LLEventStream mPump;
 	LLSD mAuthResponse, mValidAuthResponse;
@@ -123,11 +122,11 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
     // its first wait; at that point, return here.
     std::string coroname = 
         LLCoros::instance().launch("LLLogin::Impl::login_",
-                                   boost::bind(&Impl::login_, this, _1, uri, login_params));
+                                   boost::bind(&Impl::loginCoro, this, uri, login_params));
     LL_DEBUGS("LLLogin") << " connected with  uri '" << uri << "', login_params " << login_params << LL_ENDL;	
 }
 
-void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_params)
+void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
 {
 	try
 	{
@@ -137,50 +136,13 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
 	//{
 	//	printable_params["params"]["passwd"] = "*******";
 	//}
-	LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
+	LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName()
                         << " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;
 
 	// Arriving in SRVRequest state
     LLEventStream replyPump("SRVreply", true);
     // Should be an array of one or more uri strings.
 
-    LLSD rewrittenURIs;
-    {
-		LLEventTimeout filter(replyPump);
-		sendProgressEvent("offline", "srvrequest");
-
-      // Request SRV record.
-		LL_DEBUGS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
-
-      // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.
-		F32 seconds_to_timeout = 5.0f;
-		if(login_params.has("cfg_srv_timeout"))
-		{
-			seconds_to_timeout = login_params["cfg_srv_timeout"].asReal();
-		}
-
-		// If the SRV request times out (e.g. EXT-3934), simulate response: an
-		// array containing our original URI.
-		LLSD fakeResponse(LLSD::emptyArray());
-		fakeResponse.append(uri);
-		filter.eventAfter(seconds_to_timeout, fakeResponse);
-
-		std::string srv_pump_name = "LLAres";
-		if(login_params.has("cfg_srv_pump"))
-		{
-			srv_pump_name = login_params["cfg_srv_pump"].asString();
-		}
-
-		// Make request
-		LLSD request;
-		request["op"] = "rewriteURI";
-		request["uri"] = uri;
-		request["reply"] = replyPump.getName();
-		rewrittenURIs = postAndWait(self, request, srv_pump_name, filter);
-		// EXP-772: If rewrittenURIs fail, try original URI as a fallback.
-		rewrittenURIs.append(uri);
-    } // we no longer need the filter
-
     LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
     // EXT-4193: use a DIFFERENT reply pump than for the SRV request. We used
     // to share them -- but the EXT-3934 fix made it possible for an abandoned
@@ -191,107 +153,103 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
     // Because of possible redirect responses, we may make more than one
     // attempt per rewrittenURIs entry.
     LLSD::Integer attempts = 0;
-    for (LLSD::array_const_iterator urit(rewrittenURIs.beginArray()),
-             urend(rewrittenURIs.endArray());
-         urit != urend; ++urit)
+
+    LLSD request(login_params);
+    request["reply"] = loginReplyPump.getName();
+    request["uri"] = uri;
+    std::string status;
+
+    // Loop back to here if login attempt redirects to a different
+    // request["uri"]
+    for (;;)
     {
-        LLSD request(login_params);
-        request["reply"] = loginReplyPump.getName();
-        request["uri"] = *urit;
-        std::string status;
-
-        // Loop back to here if login attempt redirects to a different
-        // request["uri"]
-        for (;;)
+        ++attempts;
+        LLSD progress_data;
+        progress_data["attempt"] = attempts;
+        progress_data["request"] = request;
+		if(progress_data["request"].has("params")
+			&& progress_data["request"]["params"].has("passwd"))
+		{
+			progress_data["request"]["params"]["passwd"] = "*******";
+		}
+        sendProgressEvent("offline", "authenticating", progress_data);
+
+        // We expect zero or more "Downloading" status events, followed by
+        // exactly one event with some other status. Use postAndSuspend() the
+        // first time, because -- at least in unit-test land -- it's
+        // possible for the reply to arrive before the post() call
+        // returns. Subsequent responses, of course, must be awaited
+        // without posting again.
+        for (mAuthResponse = validateResponse(loginReplyPump.getName(),
+                    llcoro::postAndSuspend(request, xmlrpcPump, loginReplyPump, "reply"));
+                mAuthResponse["status"].asString() == "Downloading";
+                mAuthResponse = validateResponse(loginReplyPump.getName(),
+                                                llcoro::suspendUntilEventOn(loginReplyPump)))
         {
-            ++attempts;
-            LLSD progress_data;
-            progress_data["attempt"] = attempts;
-            progress_data["request"] = request;
-			if(progress_data["request"].has("params")
-				&& progress_data["request"]["params"].has("passwd"))
-			{
-				progress_data["request"]["params"]["passwd"] = "*******";
-			}
-            sendProgressEvent("offline", "authenticating", progress_data);
-
-            // We expect zero or more "Downloading" status events, followed by
-            // exactly one event with some other status. Use postAndWait() the
-            // first time, because -- at least in unit-test land -- it's
-            // possible for the reply to arrive before the post() call
-            // returns. Subsequent responses, of course, must be awaited
-            // without posting again.
-            for (mAuthResponse = validateResponse(loginReplyPump.getName(),
-                                 postAndWait(self, request, xmlrpcPump, loginReplyPump, "reply"));
-                 mAuthResponse["status"].asString() == "Downloading";
-                 mAuthResponse = validateResponse(loginReplyPump.getName(),
-                                     waitForEventOn(self, loginReplyPump)))
-            {
-                // Still Downloading -- send progress update.
-                sendProgressEvent("offline", "downloading");
-            }
+            // Still Downloading -- send progress update.
+            sendProgressEvent("offline", "downloading");
+        }
 	
-			LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
-            status = mAuthResponse["status"].asString();
-
-            // Okay, we've received our final status event for this
-            // request. Unless we got a redirect response, break the retry
-            // loop for the current rewrittenURIs entry.
-            if (!(status == "Complete" &&
-                  mAuthResponse["responses"]["login"].asString() == "indeterminate"))
-            {
-                break;
-            }
-
-			sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
-
-            // Here the login service at the current URI is redirecting us
-            // to some other URI ("indeterminate" -- why not "redirect"?).
-            // The response should contain another uri to try, with its
-            // own auth method.
-            request["uri"] = mAuthResponse["responses"]["next_url"].asString();
-            request["method"] = mAuthResponse["responses"]["next_method"].asString();
-        } // loop back to try the redirected URI
-
-        // Here we're done with redirects for the current rewrittenURIs
-        // entry.
-        if (status == "Complete")
+		LL_DEBUGS("LLLogin") << "Auth Response: " << mAuthResponse << LL_ENDL;
+        status = mAuthResponse["status"].asString();
+
+        // Okay, we've received our final status event for this
+        // request. Unless we got a redirect response, break the retry
+        // loop for the current rewrittenURIs entry.
+        if (!(status == "Complete" &&
+                mAuthResponse["responses"]["login"].asString() == "indeterminate"))
         {
-            // StatusComplete does not imply auth success. Check the
-            // actual outcome of the request. We've already handled the
-            // "indeterminate" case in the loop above.
-            if (mAuthResponse["responses"]["login"].asString() == "true")
-            {
-                sendProgressEvent("online", "connect", mAuthResponse["responses"]);
-            }
-            else
-            {
-                sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
-            }
-            return;             // Done!
+            break;
         }
 
-		/* Sometimes we end with "Started" here. Slightly slow server?
-		 * Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
-		 */
-		if( status == "Started")
-		{
-			LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
-			continue;
-		}
+		sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
 
-        // If we don't recognize status at all, trouble
-        if (! (status == "CURLError"
-               || status == "XMLRPCError"
-               || status == "OtherError"))
+        // Here the login service at the current URI is redirecting us
+        // to some other URI ("indeterminate" -- why not "redirect"?).
+        // The response should contain another uri to try, with its
+        // own auth method.
+        request["uri"] = mAuthResponse["responses"]["next_url"].asString();
+        request["method"] = mAuthResponse["responses"]["next_method"].asString();
+    } // loop back to try the redirected URI
+
+    // Here we're done with redirects for the current rewrittenURIs
+    // entry.
+    if (status == "Complete")
+    {
+        // StatusComplete does not imply auth success. Check the
+        // actual outcome of the request. We've already handled the
+        // "indeterminate" case in the loop above.
+        if (mAuthResponse["responses"]["login"].asString() == "true")
+        {
+            sendProgressEvent("online", "connect", mAuthResponse["responses"]);
+        }
+        else
         {
-            LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
-                               << mAuthResponse << LL_ENDL;
-            return;
+            sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
         }
+        return;             // Done!
+    }
 
-        // Here status IS one of the errors tested above.
-    } // Retry if there are any more rewrittenURIs.
+// 	/* Sometimes we end with "Started" here. Slightly slow server?
+// 		* Seems to be ok to just skip it. Otherwise we'd error out and crash in the if below.
+// 		*/
+// 	if( status == "Started")
+// 	{
+// 		LL_DEBUGS("LLLogin") << mAuthResponse << LL_ENDL;
+// 		continue;
+// 	}
+
+    // If we don't recognize status at all, trouble
+    if (! (status == "CURLError"
+            || status == "XMLRPCError"
+            || status == "OtherError"))
+    {
+        LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: "
+                            << mAuthResponse << LL_ENDL;
+        return;
+    }
+
+    // Here status IS one of the errors tested above.
 
     // Here we got through all the rewrittenURIs without succeeding. Tell
     // caller this didn't work out so well. Of course, the only failure data
@@ -352,29 +310,8 @@ LLEventPump& LLLogin::getEventPump()
 
 // The list associates to event with the original idle_startup() 'STATE'.
 
-// Rewrite URIs
- // State_LOGIN_AUTH_INIT
-// Given a vector of login uris (usually just one), perform a dns lookup for the 
-// SRV record from each URI. I think this is used to distribute login requests to 
-// a single URI to multiple hosts.
-// This is currently a synchronous action. (See LLSRV::rewriteURI() implementation)
-// On dns lookup error the output uris == the input uris.
-//
-// Input: A vector of login uris
-// Output: A vector of login uris
-//
-// Code:
-// std::vector<std::string> uris;
-// LLViewerLogin::getInstance()->getLoginURIs(uris);
-// std::vector<std::string>::const_iterator iter, end;
-// for (iter = uris.begin(), end = uris.end(); iter != end; ++iter)
-// {
-//	std::vector<std::string> rewritten;
-//	rewritten = LLSRV::rewriteURI(*iter);
-//	sAuthUris.insert(sAuthUris.end(),
-//					 rewritten.begin(), rewritten.end());
-// }
-// sAuthUriNum = 0;
+// Setup login
+// State_LOGIN_AUTH_INIT
 
 // Authenticate 
 // STATE_LOGIN_AUTHENTICATE
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
index 58bf371a042de9b3cf0a7e1a42c67f73db516466..e96c495446a843467527ec5975eb3c08af1c478f 100755
--- a/indra/viewer_components/login/tests/lllogin_test.cpp
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -96,61 +96,6 @@ class LoginListener: public LLEventTrackable
     }
 };
 
-class LLAresListener: public LLEventTrackable
-{
-	std::string mName;
-	LLSD mEvent;
-	bool mImmediateResponse;
-	bool mMultipleURIResponse;
-    Debug mDebug;
-	
-public:
-	LLAresListener(const std::string& name, 
-				   bool i = false,
-				   bool m = false
-				   ) : 
-		mName(name),
-		mImmediateResponse(i),
-		mMultipleURIResponse(m),
-        mDebug(stringize(*this))
-	{}
-
-	bool handle_event(const LLSD& event)
-	{
-		mDebug(STRINGIZE("LLAresListener called!: " << event));
-		mEvent = event;
-		if(mImmediateResponse)
-		{
-			sendReply();
-		}
-		return false;
-	}
-
-	void sendReply()
-	{
-		if(mEvent["op"].asString() == "rewriteURI")
-		{
-			LLSD result;
-			if(mMultipleURIResponse)
-			{
-				result.append(LLSD("login.foo.com"));
-			}
-			result.append(mEvent["uri"]);
-			LLEventPumps::instance().obtain(mEvent["reply"]).post(result);
-		}
-	}
-
-	LLBoundListener listenTo(LLEventPump& pump)
-    {
-        return pump.listen(mName, boost::bind(&LLAresListener::handle_event, this, _1));
-	}
-
-    friend std::ostream& operator<<(std::ostream& out, const LLAresListener& listener)
-    {
-        return out << "LLAresListener(" << listener.mName << ')';
-    }
-};
-
 class LLXMLRPCListener: public LLEventTrackable
 {
 	std::string mName;
@@ -232,16 +177,12 @@ namespace tut
     void llviewerlogin_object::test<1>()
     {
         DEBUG;
-		// Testing login with immediate responses from Ares and XMLPRC
-		// The response from both requests will come before the post request exits.
+		// Testing login with an immediate response from XMLPRC
+		// The response will come before the post request exits.
 		// This tests an edge case of the login state handling.
-		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
 		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
 
 		bool respond_immediately = true;
-		// Have 'dummy ares' respond immediately. 
-		LLAresListener dummyLLAres("dummy_llares", respond_immediately);
-		dummyLLAres.listenTo(llaresPump);
 
 		// Have dummy XMLRPC respond immediately.
 		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc", respond_immediately);
@@ -264,111 +205,14 @@ namespace tut
 
     template<> template<>
     void llviewerlogin_object::test<2>()
-    {
-        DEBUG;
-		// Tests a successful login in with delayed responses. 
-		// Also includes 'failure' that cause the login module
-		// to re-attempt connection, once from a basic failure
-		// and once from the 'indeterminate' response.
-
-		set_test_name("LLLogin multiple srv uris w/ success");
-
-		// Testing normal login procedure.
-		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
-		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
-
-		bool respond_immediately = false;
-		bool multiple_addresses = true;
-		LLAresListener dummyLLAres("dummy_llares", respond_immediately, multiple_addresses);
-		dummyLLAres.listenTo(llaresPump);
-
-		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
-		dummyXMLRPC.listenTo(xmlrpcPump);
-
-		LLLogin login;
-
-		LoginListener listener("test_ear");
-		listener.listenTo(login.getEventPump());
-
-		LLSD credentials;
-		credentials["first"] = "foo";
-		credentials["last"] = "bar";
-		credentials["passwd"] = "secret";
-
-		login.connect("login.bar.com", credentials);
-
-		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
-
-		dummyLLAres.sendReply();
-
-		// Test Authenticating State prior to first response.
-		ensure_equals("Auth state 1", listener.lastEvent()["change"].asString(), "authenticating"); 
-		ensure_equals("Attempt 1", listener.lastEvent()["data"]["attempt"].asInteger(), 1); 
-		ensure_equals("URI 1", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.foo.com"); 
-
-		// First send emulated LLXMLRPCListener failure,
-		// this should return login to the authenticating step and increase the attempt 
-		// count.
-		LLSD data;
-		data["status"] = "OtherError"; 
-		data["errorcode"] = 0;
-		data["error"] = "dummy response";
-		data["transfer_rate"] = 0;
-		dummyXMLRPC.setResponse(data);
-		dummyXMLRPC.sendReply();
-
-		ensure_equals("Fail back to authenticate 1", listener.lastEvent()["change"].asString(), "authenticating"); 
-		ensure_equals("Attempt 2", listener.lastEvent()["data"]["attempt"].asInteger(), 2); 
-		ensure_equals("URI 2", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com"); 
-
-		// Now send the 'indeterminate' response.
-		data.clear();
-		data["status"] = "Complete"; // StatusComplete
-		data["errorcode"] = 0;
-		data["error"] = "dummy response";
-		data["transfer_rate"] = 0;
-		data["responses"]["login"] = "indeterminate";
-		data["responses"]["next_url"] = "login.indeterminate.com";			
-		data["responses"]["next_method"] = "test_login_method"; 			
-		dummyXMLRPC.setResponse(data);
-		dummyXMLRPC.sendReply();
-
-		ensure_equals("Fail back to authenticate 2", listener.lastEvent()["change"].asString(), "authenticating"); 
-		ensure_equals("Attempt 3", listener.lastEvent()["data"]["attempt"].asInteger(), 3); 
-		ensure_equals("URI 3", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.indeterminate.com"); 
-		ensure_equals("Method 3", listener.lastEvent()["data"]["request"]["method"].asString(), "test_login_method"); 
-
-		// Finally let the auth succeed.
-		data.clear();
-		data["status"] = "Complete"; // StatusComplete
-		data["errorcode"] = 0;
-		data["error"] = "dummy response";
-		data["transfer_rate"] = 0;
-		data["responses"]["login"] = "true";
-		dummyXMLRPC.setResponse(data);
-		dummyXMLRPC.sendReply();
-
-		ensure_equals("Success state", listener.lastEvent()["state"].asString(), "online");
-
-		login.disconnect();
-
-		ensure_equals("Disconnected state", listener.lastEvent()["state"].asString(), "offline");
-	}
-
-    template<> template<>
-    void llviewerlogin_object::test<3>()
     {
         DEBUG;
 		// Test completed response, that fails to login.
 		set_test_name("LLLogin valid response, failure (eg. bad credentials)");
 
 		// Testing normal login procedure.
-		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
 		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
 
-		LLAresListener dummyLLAres("dummy_llares");
-		dummyLLAres.listenTo(llaresPump);
-
 		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
 		dummyXMLRPC.listenTo(xmlrpcPump);
 
@@ -383,10 +227,6 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
-
-		dummyLLAres.sendReply();
-
 		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
 
 		// Send the failed auth request reponse
@@ -403,19 +243,15 @@ namespace tut
 	}
 
     template<> template<>
-    void llviewerlogin_object::test<4>()
+    void llviewerlogin_object::test<3>()
     {
         DEBUG;
 		// Test incomplete response, that end the attempt.
 		set_test_name("LLLogin valid response, failure (eg. bad credentials)");
 
 		// Testing normal login procedure.
-		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
 		LLEventStream xmlrpcPump("LLXMLRPCTransaction"); // Dummy XMLRPC pump
 
-		LLAresListener dummyLLAres("dummy_llares");
-		dummyLLAres.listenTo(llaresPump);
-
 		LLXMLRPCListener dummyXMLRPC("dummy_xmlrpc");
 		dummyXMLRPC.listenTo(xmlrpcPump);
 
@@ -430,10 +266,6 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV state", listener.lastEvent()["change"].asString(), "srvrequest"); 
-
-		dummyLLAres.sendReply();
-
 		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
 
 		// Send the failed auth request reponse
@@ -449,17 +281,13 @@ namespace tut
 	}
 
 	template<> template<>
-    void llviewerlogin_object::test<5>()
+    void llviewerlogin_object::test<4>()
     {
         DEBUG;
 		// Test SRV request timeout.
 		set_test_name("LLLogin SRV timeout testing");
 
 		// Testing normal login procedure.
-		LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
-
-		LLAresListener dummyLLAres("dummy_llares");
-		dummyLLAres.listenTo(llaresPump);
 
 		LLLogin login;
 		LoginListener listener("test_ear");
@@ -473,26 +301,15 @@ namespace tut
 
 		login.connect("login.bar.com", credentials);
 
-		ensure_equals("SRV State", listener.lastEvent()["change"].asString(), "srvrequest"); 
-
 		// Get the mainloop eventpump, which needs a pinging in order to drive the 
 		// SRV timeout.
 		LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
 		LLSD frame_event;
 		mainloop.post(frame_event);
 
-		// In this state we have NOT sent a reply from LLAresListener -- in
-		// fact there's no such object. Nonetheless, we expect the timeout to
-		// have stepped the login module forward to try to authenticate with
-		// the original URI.
 		ensure_equals("Auth state", listener.lastEvent()["change"].asString(), "authenticating"); 
 		ensure_equals("Attempt", listener.lastEvent()["data"]["attempt"].asInteger(), 1); 
 		ensure_equals("URI", listener.lastEvent()["data"]["request"]["uri"].asString(), "login.bar.com");
 
-		// EXT-4193: if the SRV reply isn't lost but merely late, and if it
-		// arrives just at the moment we're expecting the XMLRPC reply, the
-		// original code got confused and crashed. Drive that case here. We
-		// observe that without the fix, this call DOES repro.
-		dummyLLAres.sendReply();
 	}
 }
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
index 61fd4220e0d310461ba59a1a2409781808dcad19..48c065c2edc19924a0bc31735525c59a5cb02f24 100755
--- a/indra/viewer_components/updater/CMakeLists.txt
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -6,15 +6,18 @@ include(00-Common)
 if(LL_TESTS)
   include(LLAddBuildTest)
 endif(LL_TESTS)
+include(Boost)
 include(CMakeCopyIfDifferent)
 include(CURL)
 include(LLCommon)
+include(LLCoreHttp)
 include(LLMessage)
 include(LLPlugin)
 include(LLVFS)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLMESSAGE_INCLUDE_DIRS}
     ${LLPLUGIN_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
@@ -60,6 +63,7 @@ add_library(llupdaterservice
 target_link_libraries(llupdaterservice
     ${LLCOMMON_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLPLUGIN_LIBRARIES}
     ${LLVFS_LIBRARIES}
     )
@@ -69,14 +73,16 @@ if(LL_TESTS)
       llupdaterservice.cpp
       )
 
+
+set_source_files_properties(
+    llupdaterservice.cpp
+    PROPERTIES
+      LL_TEST_ADDITIONAL_LIBRARIES "${BOOST_SYSTEM_LIBRARY}"
 # *NOTE:Mani - I was trying to use the preprocessor seam to mock out
-#              llifstream (and other) llcommon classes. I didn't work
+#              llifstream (and other) llcommon classes. It didn't work
 #              because of the windows declspec(dllimport)attribute.
-#set_source_files_properties(
-#    llupdaterservice.cpp
-#    PROPERTIES
-#      LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream"
-#    )
+#     LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream"
+    )
 
   LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}")
 endif(LL_TESTS)
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
index 8da4f88905c51f9ad365c7e4007352480858268a..1bb5e95740261845eeafe56457aeb93295469acd 100755
--- a/indra/viewer_components/updater/llupdatechecker.cpp
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -26,10 +26,10 @@
 #include "linden_common.h"
 #include <stdexcept>
 #include <boost/format.hpp>
-#include "llhttpclient.h"
 #include "llsd.h"
 #include "llupdatechecker.h"
 #include "lluri.h"
+#include "llcorehttputil.h"
 #if LL_DARWIN
 #include <CoreServices/CoreServices.h>
 #endif
@@ -53,15 +53,12 @@ class LLUpdateChecker::CheckError:
 
 // LLUpdateChecker
 //-----------------------------------------------------------------------------
-
-
 LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
 	mImplementation(new LLUpdateChecker::Implementation(client))
 {
 	; // No op.
 }
 
-
 void LLUpdateChecker::checkVersion(std::string const & urlBase, 
 								   std::string const & channel,
 								   std::string const & version,
@@ -74,11 +71,8 @@ void LLUpdateChecker::checkVersion(std::string const & urlBase,
 }
 
 
-
 // LLUpdateChecker::Implementation
 //-----------------------------------------------------------------------------
-
-
 const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.1";
 
 
@@ -121,57 +115,58 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase,
 
 		std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test);
 		LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL;
-	
-		mHttpClient.get(checkUrl, this);
-	}
-	else
-	{
-		LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL;
-	}
-}
 
-void LLUpdateChecker::Implementation::httpCompleted()
-{
-	mInProgress = false;	
+        LLCoros::instance().launch("LLUpdateChecker::Implementation::checkVersionCoro",
+            boost::bind(&Implementation::checkVersionCoro, this, checkUrl));
 
-	S32 status = getStatus();
-	const LLSD& content = getContent();
-	const std::string& reason = getReason();
-	if(status != 200)
-	{
-		std::string server_error;
-		if ( content.has("error_code") )
-		{
-			server_error += content["error_code"].asString();
-		}
-		if ( content.has("error_text") )
-		{
-			server_error += server_error.empty() ? "" : ": ";
-			server_error += content["error_text"].asString();
-		}
-
-		LL_WARNS("UpdaterService") << "response error " << status
-								   << " " << reason
-								   << " (" << server_error << ")"
-								   << LL_ENDL;
-		mClient.error(reason);
 	}
 	else
 	{
-		mClient.response(content);
+		LL_WARNS("UpdaterService") << "attempting to restart a check when one is in progress; ignored" << LL_ENDL;
 	}
 }
 
-
-void LLUpdateChecker::Implementation::httpFailure()
+void LLUpdateChecker::Implementation::checkVersionCoro(std::string url)
 {
-	const std::string& reason = getReason();
-	mInProgress = false;
-	LL_WARNS("UpdaterService") << "update check failed; " << reason << LL_ENDL;
-	mClient.error(reason);
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("checkVersionCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    LL_INFOS("checkVersionCoro") << "Getting update information from " << url << LL_ENDL;
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    mInProgress = false;
+
+    if (status != LLCore::HttpStatus(HTTP_OK))
+    {
+        std::string server_error;
+        if (result.has("error_code"))
+        {
+            server_error += result["error_code"].asString();
+        }
+        if (result.has("error_text"))
+        {
+            server_error += server_error.empty() ? "" : ": ";
+            server_error += result["error_text"].asString();
+        }
+
+        LL_WARNS("UpdaterService") << "response error " << status.getStatus()
+            << " " << status.toString()
+            << " (" << server_error << ")"
+            << LL_ENDL;
+        mClient.error(status.toString());
+        return;
+    }
+
+    result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+    mClient.response(result);
 }
 
-
 std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase, 
 													  std::string const & channel,
 													  std::string const & version,
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
index 3163a6d53c517801c5d4509bb25809686678f2a9..d10ea4cf42e0d526699d5eb71060d245a110635c 100755
--- a/indra/viewer_components/updater/llupdatechecker.h
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -30,61 +30,27 @@
 #include <boost/shared_ptr.hpp>
 
 #include "llmd5.h"
-#include "llhttpclient.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
 
 //
 // Implements asynchronous checking for updates.
 //
 class LLUpdateChecker {
 public:
-	class Client;
-	class Implementation: public LLHTTPClient::Responder
-	{
-	public:
-		Implementation(Client & client);
-		~Implementation();
-		void checkVersion(std::string const & urlBase, 
-						  std::string const & channel,
-						  std::string const & version,
-						  std::string const & platform,
-						  std::string const & platform_version,
-						  unsigned char       uniqueid[MD5HEX_STR_SIZE],
-						  bool                willing_to_test
-						  );
-	
-    protected:
-		// Responder:
-		virtual void httpCompleted();
-		virtual void httpFailure();
-	
-	private:	
-		static const char * sLegacyProtocolVersion;
-		static const char * sProtocolVersion;
-		const char* mProtocol;
-		
-		Client & mClient;
-		LLHTTPClient mHttpClient;
-		bool         mInProgress;
-		std::string   mVersion;
-		std::string   mUrlBase;
-		std::string   mChannel;
-		std::string   mPlatform;
-		std::string   mPlatformVersion;
-		unsigned char mUniqueId[MD5HEX_STR_SIZE];
-		bool          mWillingToTest;
-		
-		std::string buildUrl(std::string const & urlBase, 
-							 std::string const & channel,
-							 std::string const & version,
-							 std::string const & platform,
-							 std::string const & platform_version,
-							 unsigned char       uniqueid[MD5HEX_STR_SIZE],
-							 bool                willing_to_test);
-
-		LOG_CLASS(LLUpdateChecker::Implementation);
-	};
+    //
+    // The client interface implemented by a requestor checking for an update.
+    //
+    class Client
+    {
+    public:
+        // An error occurred while checking for an update.
+        virtual void error(std::string const & message) = 0;
+
+        // A successful response was received from the viewer version manager
+        virtual void response(LLSD const & content) = 0;
+    };
 
-	
 	// An exception that may be raised on check errors.
 	class CheckError;
 	
@@ -100,25 +66,54 @@ class LLUpdateChecker {
 					  bool                willing_to_test);
 	
 private:
-	LLPointer<Implementation> mImplementation;
-};
+    class Implementation
+    {
+    public:
+        typedef boost::shared_ptr<Implementation> ptr_t;
 
+        Implementation(Client & client);
+        ~Implementation();
+        void checkVersion(std::string const & urlBase,
+            std::string const & channel,
+            std::string const & version,
+            std::string const & platform,
+            std::string const & platform_version,
+            unsigned char       uniqueid[MD5HEX_STR_SIZE],
+            bool                willing_to_test
+            );
 
-class LLURI; // From lluri.h
 
+    private:
+        static const char * sLegacyProtocolVersion;
+        static const char * sProtocolVersion;
+        const char* mProtocol;
 
-//
-// The client interface implemented by a requestor checking for an update.
-//
-class LLUpdateChecker::Client
-{
-public:
-	// An error occurred while checking for an update.
-	virtual void error(std::string const & message) = 0;
-	
-	// A successful response was received from the viewer version manager
-	virtual void response(LLSD const & content) = 0;
-};
+        Client & mClient;
+        bool         mInProgress;
+        std::string   mVersion;
+        std::string   mUrlBase;
+        std::string   mChannel;
+        std::string   mPlatform;
+        std::string   mPlatformVersion;
+        unsigned char mUniqueId[MD5HEX_STR_SIZE];
+        bool          mWillingToTest;
+
+        std::string buildUrl(std::string const & urlBase,
+            std::string const & channel,
+            std::string const & version,
+            std::string const & platform,
+            std::string const & platform_version,
+            unsigned char       uniqueid[MD5HEX_STR_SIZE],
+            bool                willing_to_test);
+
+        void checkVersionCoro(std::string url);
 
+        LOG_CLASS(LLUpdateChecker::Implementation);
+    };
+
+
+    Implementation::ptr_t       mImplementation;
+	//LLPointer<Implementation> mImplementation;
+};
 
 #endif
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
index f868e5cc2c537bfb7e90ac0d049eb044a02bfe9c..53c729469bc9f2bc19e5a8421a5c077b9cc2ad96 100755
--- a/indra/viewer_components/updater/llupdatedownloader.cpp
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -26,7 +26,7 @@
 #include "linden_common.h"
 
 #include "llupdatedownloader.h"
-
+#include "httpcommon.h"
 #include <stdexcept>
 #include <boost/format.hpp>
 #include <boost/lexical_cast.hpp>
@@ -39,7 +39,6 @@
 #include "llsdserialize.h"
 #include "llthread.h"
 #include "llupdaterservice.h"
-#include "llcurl.h"
 
 class LLUpdateDownloader::Implementation:
 	public LLThread
@@ -65,7 +64,7 @@ class LLUpdateDownloader::Implementation:
 	curl_off_t mBandwidthLimit;
 	bool mCancelled;
 	LLUpdateDownloader::Client & mClient;
-	CURL * mCurl;
+	LLCore::LLHttp::CURL_ptr mCurl;
 	LLSD mDownloadData;
 	llofstream mDownloadStream;
 	unsigned char mDownloadPercent;
@@ -192,7 +191,7 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &
 	mBandwidthLimit(0),
 	mCancelled(false),
 	mClient(client),
-	mCurl(0),
+	mCurl(),
 	mDownloadPercent(0),
 	mHeaderList(0)
 {
@@ -212,10 +211,7 @@ LLUpdateDownloader::Implementation::~Implementation()
 	{
 		; // No op.
 	}
-	if(mCurl)
-	{
-		LLCurl::deleteEasyHandle(mCurl);
-	}
+    mCurl.reset();
 }
 
 
@@ -331,9 +327,9 @@ void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond)
 {
 	if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean())
 	{
-		llassert(mCurl != 0);
+		llassert(static_cast<bool>(mCurl));
 		mBandwidthLimit = bytesPerSecond;
-		CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);
+		CURLcode code = curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit);
 		if(code != CURLE_OK)
 		{
 			LL_WARNS("UpdaterService") << "unable to change dowload bandwidth" << LL_ENDL;
@@ -416,7 +412,7 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b
 
 void LLUpdateDownloader::Implementation::run(void)
 {
-	CURLcode code = curl_easy_perform(mCurl);
+    CURLcode code = curl_easy_perform(mCurl.get());
 	mDownloadStream.close();
 	if(code == CURLE_OK)
 	{
@@ -460,36 +456,36 @@ void LLUpdateDownloader::Implementation::run(void)
 
 void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)
 {
-	if(mCurl == 0)
+	if(!mCurl)
 	{
-		mCurl = LLCurl::newEasyHandle();
+		mCurl = LLCore::LLHttp::createEasyHandle();
 	}
 	else
 	{
-		curl_easy_reset(mCurl);
+        curl_easy_reset(mCurl.get());
 	}
 
-	if(mCurl == 0)
+	if(!mCurl)
 	{
 		throw DownloadError("failed to initialize curl");
 	}
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this));
+    throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEFUNCTION, &write_function));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_WRITEDATA, this));
 	if(processHeader)
 	{
-	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function));
-	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this));
-	}
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this));
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false));
+	   throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERFUNCTION, &header_function));
+	   throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HEADERDATA, this));
+	}
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPGET, true));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_URL, url.c_str()));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_PROGRESSFUNCTION, &progress_callback));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_PROGRESSDATA, this));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOPROGRESS, false));
 	// if it's a required update set the bandwidth limit to 0 (unlimited)
 	curl_off_t limit = mDownloadData["required"].asBoolean() ? 0 : mBandwidthLimit;
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, limit));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_MAX_RECV_SPEED_LARGE, limit));
 
 	mDownloadPercent = 0;
 }
@@ -511,7 +507,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
 	{
 		throw DownloadError("cannot add Range header");
 	}
-	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList));
+	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList));
 
 	mDownloadStream.open(mDownloadData["path"].asString().c_str(),
 						 std::ios_base::out | std::ios_base::binary | std::ios_base::app);
diff --git a/indra/win_crash_logger/CMakeLists.txt b/indra/win_crash_logger/CMakeLists.txt
index c6070020db4973d22e92d40adb2a7486327ce868..144d037a319e69436a60d2999adc836f1c23d920 100755
--- a/indra/win_crash_logger/CMakeLists.txt
+++ b/indra/win_crash_logger/CMakeLists.txt
@@ -4,6 +4,7 @@ project(win_crash_logger)
 
 include(00-Common)
 include(LLCommon)
+include(LLCoreHttp)
 include(LLCrashLogger)
 include(LLMath)
 include(LLMessage)
@@ -13,8 +14,10 @@ include(LLXML)
 include(Linking)
 include(LLSharedLibs)
 include(GoogleBreakpad)
+include(Boost)
 
 include_directories(
+    ${LLCOREHTTP_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLCRASHLOGGER_INCLUDE_DIRS}
     ${LLMATH_INCLUDE_DIRS}
@@ -77,7 +80,10 @@ target_link_libraries(windows-crash-logger
     ${LLXML_LIBRARIES}
     ${LLMESSAGE_LIBRARIES}
     ${LLMATH_LIBRARIES}
+    ${LLCOREHTTP_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${BOOST_CONTEXT_LIBRARY}
+    ${BOOST_COROUTINE_LIBRARY}
     ${WINDOWS_LIBRARIES}
     ${DXGUID_LIBRARY}
     ${GOOGLE_PERFTOOLS_LIBRARIES}