diff options
Diffstat (limited to 'indra/viewer_components')
-rwxr-xr-x | indra/viewer_components/login/CMakeLists.txt | 8 | ||||
-rwxr-xr-x | indra/viewer_components/login/lllogin.cpp | 251 | ||||
-rwxr-xr-x | indra/viewer_components/login/tests/lllogin_test.cpp | 191 | ||||
-rwxr-xr-x | indra/viewer_components/updater/CMakeLists.txt | 28 | ||||
-rwxr-xr-x | indra/viewer_components/updater/llupdatechecker.cpp | 89 | ||||
-rwxr-xr-x | indra/viewer_components/updater/llupdatechecker.h | 121 | ||||
-rwxr-xr-x | indra/viewer_components/updater/llupdatedownloader.cpp | 77 |
7 files changed, 263 insertions, 502 deletions
diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt index c152f7c0a6..3bedeb7292 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 b8408a6fb4..53d4acc9e0 100755 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -107,9 +107,8 @@ private: } // 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 58bf371a04..e96c495446 100755 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -96,61 +96,6 @@ public: } }; -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); @@ -266,109 +207,12 @@ namespace tut 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 61fd4220e0..73e18aacb3 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,25 +63,36 @@ add_library(llupdaterservice target_link_libraries(llupdaterservice ${LLCOMMON_LIBRARIES} ${LLMESSAGE_LIBRARIES} + ${LLCOREHTTP_LIBRARIES} ${LLPLUGIN_LIBRARIES} ${LLVFS_LIBRARIES} ) if(LL_TESTS) +if (NOT LINUX) SET(llupdater_service_TEST_SOURCE_FILES llupdaterservice.cpp ) +set(test_libs + ${LLCOMMON_LIBRARIES} + ${BOOST_COROUTINE_LIBRARY} + ${BOOST_CONTEXT_LIBRARY} + ${BOOST_THREAD_LIBRARY} + ${BOOST_SYSTEM_LIBRARY}) + +set_source_files_properties( + llupdaterservice.cpp + PROPERTIES + LL_TEST_ADDITIONAL_LIBRARIES ${test_libs} # *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}") + LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}" ${test_libs}) +endif (NOT LINUX) endif(LL_TESTS) set(UPDATER_INCLUDE_DIRS diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 8da4f88905..1bb5e95740 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 @@ public: // 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 3163a6d53c..d10ea4cf42 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 @@ public: 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 f868e5cc2c..382689afa0 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 @@ -57,7 +56,7 @@ public: bool isDownloading(void); size_t onHeader(void * header, size_t size); size_t onBody(void * header, size_t size); - int onProgress(double downloadSize, double bytesDownloaded); + int onProgress(curl_off_t downloadSize, curl_off_t bytesDownloaded); void resume(void); void setBandwidthLimit(U64 bytesPerSecond); @@ -65,7 +64,7 @@ private: curl_off_t mBandwidthLimit; bool mCancelled; LLUpdateDownloader::Client & mClient; - CURL * mCurl; + LLCore::LLHttp::CURL_ptr mCurl; LLSD mDownloadData; llofstream mDownloadStream; unsigned char mDownloadPercent; @@ -175,11 +174,11 @@ namespace { } - int progress_callback(void * downloader, - double dowloadTotal, - double downloadNow, - double uploadTotal, - double uploadNow) + int xferinfo_callback(void * downloader, + curl_off_t dowloadTotal, + curl_off_t downloadNow, + curl_off_t uploadTotal, + curl_off_t uploadNow) { return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)-> onProgress(dowloadTotal, downloadNow); @@ -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; @@ -390,9 +386,9 @@ size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) } -int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double bytesDownloaded) +int LLUpdateDownloader::Implementation::onProgress(curl_off_t downloadSize, curl_off_t bytesDownloaded) { - int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize)); + int downloadPercent = static_cast<int>(100.0 * ((double) bytesDownloaded / (double) downloadSize)); if(downloadPercent > mDownloadPercent) { mDownloadPercent = downloadPercent; @@ -400,8 +396,8 @@ int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double b event["pump"] = LLUpdaterService::pumpName(); LLSD payload; payload["type"] = LLSD(LLUpdaterService::PROGRESS); - payload["download_size"] = downloadSize; - payload["bytes_downloaded"] = bytesDownloaded; + payload["download_size"] = (LLSD::Integer) downloadSize; + payload["bytes_downloaded"] = (LLSD::Integer) bytesDownloaded; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); @@ -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,39 @@ 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_XFERINFOFUNCTION, &xferinfo_callback)); + throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_XFERINFODATA, this)); + throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOPROGRESS, 0)); // 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)); + throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_CAINFO, gDirUtilp->getCAFile().c_str())); + throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_SSL_VERIFYHOST, 2)); + throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_SSL_VERIFYPEER, 1)); mDownloadPercent = 0; } @@ -511,7 +510,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); |