diff options
Diffstat (limited to 'indra/viewer_components')
| -rw-r--r-- | indra/viewer_components/login/lllogin.cpp | 89 | ||||
| -rw-r--r-- | indra/viewer_components/login/tests/lllogin_test.cpp | 74 |
2 files changed, 138 insertions, 25 deletions
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 7a30315b9a..b9f61ca7e1 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -70,7 +70,7 @@ public: LLEventPump& getEventPump() { return mPump; } private: - void sendProgressEvent(const std::string& state, const std::string& change, + LLSD getProgressEventLLSD(const std::string& state, const std::string& change, const LLSD& data = LLSD()) { LLSD status_data; @@ -87,7 +87,13 @@ private: { status_data["data"] = data; } + return status_data; + } + void sendProgressEvent(const std::string& state, const std::string& change, + const LLSD& data = LLSD()) + { + LLSD status_data = getProgressEventLLSD(state, change, data); mPump.post(status_data); } @@ -127,10 +133,17 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& credentials) void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credentials) { - LL_INFOS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self) - << " with uri '" << uri << "', credentials " << credentials << LL_ENDL; - // Arriving in SRVRequest state - LLEventStream replyPump("reply", true); + LLSD printable_credentials = credentials; + if(printable_credentials.has("params") + && printable_credentials["params"].has("passwd")) + { + printable_credentials["params"]["passwd"] = "*******"; + } + LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self) + << " with uri '" << uri << "', credentials " << printable_credentials << LL_ENDL; + + // Arriving in SRVRequest state + LLEventStream replyPump("SRVreply", true); // Should be an array of one or more uri strings. LLSD rewrittenURIs; { @@ -138,20 +151,40 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential sendProgressEvent("offline", "srvrequest"); // Request SRV record. - LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL; + LL_DEBUGS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL; - // *NOTE:Mani - Completely arbitrary timeout value for SRV request. - filter.errorAfter(5, "SRV Request timed out!"); + // *NOTE:Mani - Completely arbitrary default timeout value for SRV request. + F32 seconds_to_timeout = 5.0f; + if(credentials.has("cfg_srv_timeout")) + { + seconds_to_timeout = credentials["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(credentials.has("cfg_srv_pump")) + { + srv_pump_name = credentials["cfg_srv_pump"].asString(); + } - // Make request + // Make request LLSD request; request["op"] = "rewriteURI"; request["uri"] = uri; request["reply"] = replyPump.getName(); - rewrittenURIs = postAndWait(self, request, "LLAres", filter); + rewrittenURIs = postAndWait(self, request, srv_pump_name, filter); } // 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 + // SRV response to arrive just as we were expecting the XMLRPC response. + LLEventStream loginReplyPump("loginreply", true); // Loop through the rewrittenURIs, counting attempts along the way. // Because of possible redirect responses, we may make more than one @@ -162,7 +195,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential urit != urend; ++urit) { LLSD request(credentials); - request["reply"] = replyPump.getName(); + request["reply"] = loginReplyPump.getName(); request["uri"] = *urit; std::string status; @@ -174,6 +207,11 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential 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 @@ -182,32 +220,36 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // possible for the reply to arrive before the post() call // returns. Subsequent responses, of course, must be awaited // without posting again. - for (mAuthResponse = validateResponse(replyPump.getName(), - postAndWait(self, request, xmlrpcPump, replyPump, "reply")); + for (mAuthResponse = validateResponse(loginReplyPump.getName(), + postAndWait(self, request, xmlrpcPump, loginReplyPump, "reply")); mAuthResponse["status"].asString() == "Downloading"; - mAuthResponse = validateResponse(replyPump.getName(), - waitForEventOn(self, replyPump))) + mAuthResponse = validateResponse(loginReplyPump.getName(), + waitForEventOn(self, loginReplyPump))) { // 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")) + 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["next_url"]; - request["method"] = mAuthResponse["next_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 @@ -243,7 +285,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential // Here we got through all the rewrittenURIs without succeeding. Tell // caller this didn't work out so well. Of course, the only failure data // we can reasonably show are from the last of the rewrittenURIs. - sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + + // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an + // llsd with no "responses" node. To make the output from an incomplete login symmetrical + // to success, add a data/message and data/reason fields. + LLSD error_response; + error_response["reason"] = mAuthResponse["status"]; + error_response["message"] = mAuthResponse["error"]; + sendProgressEvent("offline", "fail.login", error_response); } void LLLogin::Impl::disconnect() diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp index a8ae2883d5..51f5cd0692 100644 --- a/indra/viewer_components/login/tests/lllogin_test.cpp +++ b/indra/viewer_components/login/tests/lllogin_test.cpp @@ -29,6 +29,20 @@ #include "llevents.h" #include "stringize.h" +#if LL_WINDOWS +#define skipwin(arg) skip(arg) +#define skipmac(arg) +#define skiplinux(arg) +#elif LL_DARWIN +#define skipwin(arg) +#define skipmac(arg) skip(arg) +#define skiplinux(arg) +#elif LL_LINUX +#define skipwin(arg) +#define skipmac(arg) +#define skiplinux(arg) skip(arg) +#endif + /***************************************************************************** * Helper classes *****************************************************************************/ @@ -47,6 +61,7 @@ public: bool call(const LLSD& event) { mDebug(STRINGIZE("LoginListener called!: " << event)); + mLastEvent = event; return false; } @@ -200,14 +215,14 @@ namespace tut void llviewerlogin_object::test<1>() { DEBUG; - // Testing login with immediate repsonses from Ares and XMLPRC + // Testing login with immediate responses from Ares and XMLPRC // The response from both requests 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' repsond immediately. + // Have 'dummy ares' respond immediately. LLAresListener dummyLLAres("dummy_llares", respond_immediately); dummyLLAres.listenTo(llaresPump); @@ -236,7 +251,7 @@ namespace tut 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 + // to re-attempt connection, once from a basic failure // and once from the 'indeterminate' response. set_test_name("LLLogin multiple srv uris w/ success"); @@ -296,14 +311,15 @@ namespace tut data["error"] = "dummy response"; data["transfer_rate"] = 0; data["responses"]["login"] = "indeterminate"; - data["next_url"] = "login.indeterminate.com"; - data["next_method"] = "test_login_method"; + 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(); @@ -414,4 +430,52 @@ namespace tut ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline"); } + + template<> template<> + void llviewerlogin_object::test<5>() + { + 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"); + listener.listenTo(login.getEventPump()); + + LLSD credentials; + credentials["first"] = "these"; + credentials["last"] = "don't"; + credentials["passwd"] = "matter"; + credentials["cfg_srv_timeout"] = 0.0f; + + 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(); + } } |
