diff options
author | Rider Linden <rider@lindenlab.com> | 2015-09-21 10:59:58 -0700 |
---|---|---|
committer | Rider Linden <rider@lindenlab.com> | 2015-09-21 10:59:58 -0700 |
commit | 1eed334e7ff1ce261f740f5da7207a65c3f4ef57 (patch) | |
tree | d884475cfd0731743d716393029394d99ec17638 /indra | |
parent | cf835a80cd2bb5d02cc03034009919e0d9eb73b6 (diff) |
MAINT-5629: Remove llares and llareslistener. Login now does not attempt to do a lookup on the server names and rewrite the URL.
MAINT-5614: Bad password status correctly detected.
Diffstat (limited to 'indra')
-rwxr-xr-x | indra/llmessage/CMakeLists.txt | 4 | ||||
-rwxr-xr-x | indra/llmessage/llares.cpp | 839 | ||||
-rwxr-xr-x | indra/llmessage/llares.h | 583 | ||||
-rwxr-xr-x | indra/llmessage/llareslistener.cpp | 104 | ||||
-rwxr-xr-x | indra/llmessage/llareslistener.h | 53 | ||||
-rwxr-xr-x | indra/newview/llappviewer.cpp | 25 | ||||
-rwxr-xr-x | indra/newview/llstartup.cpp | 8 | ||||
-rwxr-xr-x | indra/viewer_components/login/lllogin.cpp | 221 | ||||
-rwxr-xr-x | indra/viewer_components/login/tests/lllogin_test.cpp | 191 |
9 files changed, 94 insertions, 1934 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 3bcee13d28..5877c4a8e4 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -28,8 +28,6 @@ include_directories( ) set(llmessage_SOURCE_FILES - llares.cpp - llareslistener.cpp llassetstorage.cpp llavatarname.cpp llavatarnamecache.cpp @@ -109,8 +107,6 @@ set(llmessage_SOURCE_FILES set(llmessage_HEADER_FILES CMakeLists.txt - llares.h - llareslistener.h llassetstorage.h llavatarname.h llavatarnamecache.h diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp deleted file mode 100755 index 9f90ae1544..0000000000 --- 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 c727363b60..0000000000 --- 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 3d65906b98..0000000000 --- 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 780dcdd9c5..0000000000 --- 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/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ba76341b69..5cf9efa04e 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -57,7 +57,6 @@ #include "llfocusmgr.h" #include "llviewerjoystick.h" #include "llallocator.h" -#include "llares.h" #include "llcalc.h" #include "llconversationlog.h" #include "lldxhardware.h" @@ -1283,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"); @@ -1425,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(); } @@ -2014,9 +1992,6 @@ bool LLAppViewer::cleanup() // Non-LLCurl libcurl library mAppCoreHttp.cleanup(); - // NOTE The following call is not thread safe. - ll_cleanup_ares(); - LLFilePickerThread::cleanupClass(); //MUST happen AFTER LLCurl::cleanupClass diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 047e23cefc..7616f65a29 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" @@ -444,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 // diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index ad3d84b8e5..b361bbb276 100755 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -108,7 +108,7 @@ private: // In a coroutine's top-level function args, do NOT NOT NOT accept // references (const or otherwise) to anything! Pass by value only! - void login_(std::string uri, LLSD credentials); + void loginCoro(std::string uri, LLSD credentials); LLEventStream mPump; LLSD mAuthResponse, mValidAuthResponse; @@ -122,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, 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_(std::string uri, LLSD login_params) +void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params) { try { @@ -143,43 +143,6 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) 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 = llcoro::postAndSuspend(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 @@ -190,107 +153,103 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) // 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 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))) - { - // 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"]); + + // 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 - // If we don't recognize status at all, trouble - if (! (status == "CURLError" - || status == "XMLRPCError" - || status == "OtherError")) + // 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") { - LL_ERRS("LLLogin") << "Unexpected status from " << xmlrpcPump.getName() << " pump: " - << mAuthResponse << LL_ENDL; - return; + sendProgressEvent("online", "connect", mAuthResponse["responses"]); } + else + { + sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]); + } + return; // Done! + } + +// /* 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. - } // Retry if there are any more rewrittenURIs. + // 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 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(); } } |