From 215f423cbe18fe9ca14a26caef918d303bad28ff Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:45:11 -0500 Subject: Second Life viewer sources 1.18.4.0-RC --- linden/indra/newview/llsrv.cpp | 353 ++--------------------------------------- 1 file changed, 17 insertions(+), 336 deletions(-) (limited to 'linden/indra/newview/llsrv.cpp') diff --git a/linden/indra/newview/llsrv.cpp b/linden/indra/newview/llsrv.cpp index 5a623bc..150fcb1 100644 --- a/linden/indra/newview/llsrv.cpp +++ b/linden/indra/newview/llsrv.cpp @@ -2,7 +2,9 @@ * @file llsrv.cpp * @brief Wrapper for DNS SRV record lookups * - * Copyright (c) 2007-2007, Linden Research, Inc. + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -24,352 +26,31 @@ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llsrv.h" +#include "llares.h" -using namespace std; - -#if LL_WINDOWS - -#undef UNICODE -#include -#include - -vector LLSRV::query(const string& name) -{ - vector recs; - DNS_RECORD *rec; - DNS_STATUS status; - - status = DnsQuery(name.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &rec, NULL); - if (!status) - { - for (DNS_RECORD *cur = rec; cur != NULL; cur = cur->pNext) - { - if (cur->wType != DNS_TYPE_SRV) - { - continue; - } - recs.push_back(LLSRVRecord(cur->Data.Srv.wPriority, - cur->Data.Srv.wWeight, - cur->Data.Srv.pNameTarget, - cur->Data.Srv.wPort)); - } - DnsRecordListFree(rec, DnsFreeRecordListDeep); - } - - return recs; -} - -#else // !LL_WINDOWS - -#include -#include -#include -#include - -#include - -#ifdef HOMEGROWN_RESPONSE_PARSER - -// We ought to be using libresolv's ns_initparse and ns_parserr to -// parse the result of our query. However, libresolv isn't packaged -// correctly on Linux (as of BIND 9), so neither of these functions is -// available without statically linking against libresolv. Ugh! This -// fallback function is available if we need to parse the response -// ourselves without relying too much on libresolv. It is NOT THE -// DEFAULT. - -vector LLSRV::parseResponse(const unsigned char *response, - int resp_len) -{ - vector recs; - - const unsigned char *pos = response + sizeof(HEADER); - const unsigned char *end = response + resp_len; - const HEADER *hdr = (const HEADER *) response; - char name[1024]; - - // Skip over the query embedded in the response. - - for (int q = ntohs(hdr->qdcount); q > 0; --q) - { - int len = dn_expand(response, end, pos, name, sizeof(name)); - - if (len == -1) - { - llinfos << "Could not expand queried name in RR response" - << llendl; - goto bail; - } - - pos += len + NS_QFIXEDSZ; - } - - for (int a = ntohs(hdr->ancount); a > 0; --a) - { - static const ns_rr *rr; - - int len = dn_expand(response, end, pos, name, sizeof(name) - 1); - if (len == -1) - { - llinfos << "Could not expand response name in RR response" - << llendl; - goto bail; - } - - // Skip over the resource name and headers we don't care about. - - pos += len + sizeof(rr->type) + sizeof(rr->rr_class) + - sizeof(rr->ttl) + sizeof(rr->rdlength); - - U16 prio; - U16 weight; - U16 port; - - NS_GET16(prio, pos); - NS_GET16(weight, pos); - NS_GET16(port, pos); - - len = dn_expand(response, end, pos, name, sizeof(name) - 1); - - if (len == -1) - { - llinfos << "Could not expand name in RR response" << llendl; - goto bail; - } - - recs.push_back(LLSRVRecord(prio, weight, name, port)); - } - - // There are likely to be more records in the response, but we - // don't care about those, at least for now. -bail: - return reorder(recs); -} - -#else // HOMEGROWN_RESPONSE_PARSER - -// This version of the response parser is the one to use if libresolv -// is available and behaving itself. - -vector LLSRV::parseResponse(const unsigned char *response, - int resp_len) -{ - vector recs; - ns_msg hdr; - - if (ns_initparse(response, resp_len, &hdr)) - { - llinfos << "Could not parse response" << llendl; - goto bail; - } - - for (int i = 0; i < ns_msg_count(hdr, ns_s_an); i++) - { - ns_rr rr; - - if (ns_parserr(&hdr, ns_s_an, i, &rr)) - { - llinfos << "Could not parse RR" << llendl; - goto bail; - } - - if (ns_rr_type(rr) != ns_t_srv) - { - continue; - } - - const unsigned char *pos = ns_rr_rdata(rr); - U16 prio, weight, port; - char name[1024]; - int ret; - - NS_GET16(prio, pos); - NS_GET16(weight, pos); - NS_GET16(port, pos); - - ret = dn_expand(ns_msg_base(hdr), ns_msg_end(hdr), pos, - name, sizeof(name)); - - if (ret == -1) - { - llinfos << "Could not decompress name" << llendl; - goto bail; - } - - recs.push_back(LLSRVRecord(prio, weight, name, port)); - } - -bail: - return reorder(recs); -} - -#endif // HOMEGROWN_RESPONSE_PARSER - -vector LLSRV::query(const string& queryName) -{ - unsigned char response[16384]; - vector recs; - int len; - - len = res_query(queryName.c_str(), ns_c_in, ns_t_srv, response, - sizeof(response)); - - if (len == -1) - { - llinfos << "Query failed for " << queryName << llendl; - goto bail; - } - else if (len > (int) sizeof(response)) - { - llinfos << "Response too big for " << queryName - << " (capacity " << sizeof(response) - << ", response " << len << ")" << llendl; - goto bail; - } - - recs = parseResponse(response, len); -bail: - return reorder(recs); -} - -#endif // LL_WINDOWS - -// Implement the algorithm specified in RFC 2782 for dealing with RRs -// of differing priorities and weights. -vector LLSRV::reorder(vector& recs) +struct Responder : public LLAres::UriRewriteResponder { - typedef list reclist_t; - typedef map bucket_t; - vector newRecs; - bucket_t buckets; - - // Don't rely on the DNS server to shuffle responses. - - random_shuffle(recs.begin(), recs.end()); - - for (vector::const_iterator iter = recs.begin(); - iter != recs.end(); ++iter) - { - buckets[iter->priority()].push_back(&*iter); - } - - // Priorities take precedence over weights. - - for (bucket_t::iterator iter = buckets.begin(); - iter != buckets.end(); ++iter) - { - reclist_t& myPrio = iter->second; - reclist_t r; - - // RRs with weight zero go to the front of the intermediate - // list, so they'll have little chance of being chosen. - // Larger weights have a higher likelihood of selection. - - for (reclist_t::iterator i = myPrio.begin(); i != myPrio.end(); ) - { - if ((*i)->weight() == 0) - { - r.push_back(*i); - i = myPrio.erase(i); - } else { - ++i; - } - } - - r.insert(r.end(), myPrio.begin(), myPrio.end()); - - while (!r.empty()) + std::vector mUris; + void rewriteResult(const std::vector &uris) { + for (size_t i = 0; i < uris.size(); i++) { - U32 total = 0; - - for (reclist_t::const_iterator i = r.begin(); i != r.end(); ++i) - { - total += (*i)->weight(); - } - - U32 target = total > 1 ? (rand() % total) : 0; - U32 partial = 0; - - for (reclist_t::iterator i = r.begin(); i != r.end(); ) - { - partial += (*i)->weight(); - if (partial >= target) - { - newRecs.push_back(**i); - i = r.erase(i); - } else { - ++i; - } - } + llinfos << "[" << i << "] " << uris[i] << llendl; } + mUris = uris; } - - // Order RRs by lowest numeric priority. The stable sort - // preserves the weight choices we made above. +}; - stable_sort(newRecs.begin(), newRecs.end(), - LLSRVRecord::ComparePriorityLowest()); - - return newRecs; -} - -vector LLSRV::rewriteURI(const string& uriStr) +std::vector LLSRV::rewriteURI(const std::string& uri) { - LLURI uri(uriStr); - const string& scheme = uri.scheme(); - llinfos << "Rewriting " << uriStr << llendl; - string serviceName("_" + scheme + "._tcp." + uri.hostName()); - llinfos << "Querying for " << serviceName << llendl; - vector srvs(LLSRV::query(serviceName)); - vector rewritten; - - if (srvs.empty()) - { - llinfos << "No query results; using " << uriStr << llendl; - rewritten.push_back(uriStr); - } - else - { - vector::const_iterator iter; - size_t maxSrvs = 3; - size_t i; - - llinfos << "Got " << srvs.size() << " results" << llendl; - for (iter = srvs.begin(); iter != srvs.end(); ++iter) - { - lldebugs << "host " << iter->target() << ':' << iter->port() - << " prio " << iter->priority() - << " weight " << iter->weight() - << llendl; - } - - if (srvs.size() > maxSrvs) - { - llinfos << "Clamping to " << maxSrvs << llendl; - } - - for (iter = srvs.begin(), i = 0; - iter != srvs.end() && i < maxSrvs; ++iter, ++i) - { - LLURI newUri(scheme, - uri.userName(), - uri.password(), - iter->target(), - uri.defaultPort() ? iter->port() : uri.hostPort(), - uri.escapedPath(), - uri.escapedQuery()); - string newUriStr(newUri.asString()); - - llinfos << "Rewrite[" << i << "] " << newUriStr << llendl; - - rewritten.push_back(newUriStr); - } - } + LLPointer resp = new Responder; - return rewritten; + gAres->rewriteURI(uri, resp); + gAres->processAll(); + return resp->mUris; } -- cgit v1.1