From a408bac29378072fbf36864164149458c978cfcc Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:59 -0500 Subject: Second Life viewer sources 1.17.1.0 --- linden/indra/newview/llsrv.cpp | 213 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 linden/indra/newview/llsrv.cpp (limited to 'linden/indra/newview/llsrv.cpp') diff --git a/linden/indra/newview/llsrv.cpp b/linden/indra/newview/llsrv.cpp new file mode 100644 index 0000000..4dec48d --- /dev/null +++ b/linden/indra/newview/llsrv.cpp @@ -0,0 +1,213 @@ +/** + * @file llsrv.cpp + * @brief Wrapper for DNS SRV record lookups + * + * Copyright (c) 2007-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llsrv.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 + +vector LLSRV::query(const string& queryName) +{ + unsigned char response[16384]; + vector recs; + char name[1024]; + 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; + return recs; + } + else if (len > (int) sizeof(response)) + { + llinfos << "Response too big for " << queryName + << " (capacity " << sizeof(response) + << ", response " << len << ")" << llendl; + return recs; + } + + // We "should" 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! So we parse the response ourselves. + + const unsigned char *pos = response + sizeof(HEADER); + const unsigned char *end = response + len; + const HEADER *hdr = (const HEADER *) response; + + // Skip over the query embedded in the response. + + for (int q = ntohs(hdr->qdcount); q > 0; --q) + { + len = dn_expand(response, end, pos, name, sizeof(name)); + + if (len == -1) + { + llinfos << "Could not expand queried name in RR response" << llendl; + return recs; + } + + pos += len + NS_QFIXEDSZ; + } + + for (int a = ntohs(hdr->ancount); a > 0; --a) + { + static const ns_rr *rr; + + len = dn_expand(response, end, pos, name, sizeof(name) - 1); + if (len == -1) + { + llinfos << "Could not expand response name in RR response" << llendl; + return recs; + } + + // 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; + return recs; + } + + 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. + + return recs; +} + +#endif // LL_WINDOWS + +vector LLSRV::rewriteURI(const string& uriStr) +{ + 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; + 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); + } + } + + return rewritten; +} -- cgit v1.1