llares.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:17k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llares.cpp
  3.  * @author Bryan O'Sullivan
  4.  * @date 2007-08-15
  5.  * @brief Wrapper for asynchronous DNS lookups.
  6.  *
  7.  * $LicenseInfo:firstyear=2007&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2007-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "linden_common.h"
  35. #include "llares.h"
  36. #include <ares_dns.h>
  37. #include <ares_version.h>
  38. #include "apr_portable.h"
  39. #include "apr_network_io.h"
  40. #include "apr_poll.h"
  41. #include "llapr.h"
  42. #include "llareslistener.h"
  43. #if defined(LL_WINDOWS)
  44. #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
  45. # define ns_c_in 1
  46. # define NS_HFIXEDSZ     12      /* #/bytes of fixed data in header */
  47. # define NS_QFIXEDSZ     4       /* #/bytes of fixed data in query */
  48. # define NS_RRFIXEDSZ    10      /* #/bytes of fixed data in r record */
  49. #else
  50. # include <arpa/nameser.h>
  51. #endif
  52. LLAres::HostResponder::~HostResponder()
  53. {
  54. }
  55. void LLAres::HostResponder::hostResult(const hostent *ent)
  56. {
  57. llinfos << "LLAres::HostResponder::hostResult not implemented" << llendl;
  58. }
  59. void LLAres::HostResponder::hostError(int code)
  60. {
  61. llinfos << "LLAres::HostResponder::hostError " << code << ": "
  62. << LLAres::strerror(code) << llendl;
  63. }
  64. LLAres::NameInfoResponder::~NameInfoResponder()
  65. {
  66. }
  67. void LLAres::NameInfoResponder::nameInfoResult(const char *node,
  68.    const char *service)
  69. {
  70. llinfos << "LLAres::NameInfoResponder::nameInfoResult not implemented"
  71. << llendl;
  72. }
  73. void LLAres::NameInfoResponder::nameInfoError(int code)
  74. {
  75. llinfos << "LLAres::NameInfoResponder::nameInfoError " << code << ": "
  76. << LLAres::strerror(code) << llendl;
  77. }
  78. LLAres::QueryResponder::~QueryResponder()
  79. {
  80. }
  81. void LLAres::QueryResponder::queryResult(const char *buf, size_t len)
  82. {
  83. llinfos << "LLAres::QueryResponder::queryResult not implemented"
  84. << llendl;
  85. }
  86. void LLAres::QueryResponder::queryError(int code)
  87. {
  88. llinfos << "LLAres::QueryResponder::queryError " << code << ": "
  89. << LLAres::strerror(code) << llendl;
  90. }
  91. LLAres::LLAres() :
  92.     chan_(NULL),
  93.     mInitSuccess(false),
  94.     mListener(new LLAresListener(this))
  95. {
  96. if (ares_init(&chan_) != ARES_SUCCESS)
  97. {
  98. llwarns << "Could not succesfully initialize ares!" << llendl;
  99. return;
  100. }
  101. mInitSuccess = true;
  102. }
  103. LLAres::~LLAres()
  104. {
  105. ares_destroy(chan_);
  106. }
  107. void LLAres::cancel()
  108. {
  109. ares_cancel(chan_);
  110. }
  111. static void host_callback_1_5(void *arg, int status, int timeouts,
  112.   struct hostent *ent)
  113. {
  114. LLPointer<LLAres::HostResponder> *resp =
  115. (LLPointer<LLAres::HostResponder> *) arg;
  116. if (status == ARES_SUCCESS)
  117. {
  118. (*resp)->hostResult(ent);
  119. } else {
  120. (*resp)->hostError(status);
  121. }
  122. delete resp;
  123. }
  124. #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
  125. static void host_callback(void *arg, int status, struct hostent *ent)
  126. {
  127. host_callback_1_5(arg, status, 0, ent);
  128. }
  129. #else
  130. # define host_callback host_callback_1_5
  131. #endif
  132. void LLAres::getHostByName(const char *name, HostResponder *resp,
  133.    int family)
  134. {
  135. ares_gethostbyname(chan_, name, family, host_callback,
  136.    new LLPointer<LLAres::HostResponder>(resp));
  137. }
  138. void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp)
  139. {
  140. search(name, RES_SRV, resp);
  141. }
  142. void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp)
  143. {
  144. llinfos << "Rewriting " << uri << llendl;
  145. resp->mUri = LLURI(uri);
  146. search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(),
  147.    RES_SRV, resp);
  148. }
  149. LLQueryResponder::LLQueryResponder()
  150. : LLAres::QueryResponder(),
  151.   mResult(ARES_ENODATA),
  152.   mType(RES_INVALID)
  153. {
  154. }
  155. int LLQueryResponder::parseRR(const char *buf, size_t len, const char *&pos,
  156.   LLPointer<LLDnsRecord> &r)
  157. {
  158. std::string rrname;
  159. size_t enclen;
  160. int ret;
  161. // RR name.
  162. ret = LLAres::expandName(pos, buf, len, rrname, enclen);
  163. if (ret != ARES_SUCCESS)
  164. {
  165. return ret;
  166. }
  167. pos += enclen;
  168. if (pos + NS_RRFIXEDSZ > buf + len)
  169. {
  170. return ARES_EBADRESP;
  171. }
  172. int rrtype = DNS_RR_TYPE(pos);
  173. int rrclass = DNS_RR_CLASS(pos);
  174. int rrttl = DNS_RR_TTL(pos);
  175. int rrlen = DNS_RR_LEN(pos);
  176. if (rrclass != ns_c_in)
  177. {
  178. return ARES_EBADRESP;
  179. }
  180. pos += NS_RRFIXEDSZ;
  181. if (pos + rrlen > buf + len)
  182. {
  183. return ARES_EBADRESP;
  184. }
  185. switch (rrtype)
  186. {
  187. case RES_A:
  188. r = new LLARecord(rrname, rrttl);
  189. break;
  190. case RES_NS:
  191. r = new LLNsRecord(rrname, rrttl);
  192. break;
  193. case RES_CNAME:
  194. r = new LLCnameRecord(rrname, rrttl);
  195. break;
  196. case RES_PTR:
  197. r = new LLPtrRecord(rrname, rrttl);
  198. break;
  199. case RES_AAAA:
  200. r = new LLAaaaRecord(rrname, rrttl);
  201. break;
  202. case RES_SRV:
  203. r = new LLSrvRecord(rrname, rrttl);
  204. break;
  205. default:
  206. llinfos << "LLQueryResponder::parseRR got unknown RR type " << rrtype
  207. << llendl;
  208. return ARES_EBADRESP;
  209. }
  210. ret = r->parse(buf, len, pos, rrlen);
  211. if (ret == ARES_SUCCESS)
  212. {
  213. pos += rrlen;
  214. } else {
  215. r = NULL;
  216. }
  217. return ret;
  218. }
  219. int LLQueryResponder::parseSection(const char *buf, size_t len,
  220.    size_t count, const char *&pos,
  221.    dns_rrs_t &rrs)
  222. {
  223. int ret = ARES_SUCCESS;
  224. for (size_t i = 0; i < count; i++)
  225. {
  226. LLPointer<LLDnsRecord> r;
  227. ret = parseRR(buf, len, pos, r);
  228. if (ret != ARES_SUCCESS)
  229. {
  230. break;
  231. }
  232. rrs.push_back(r);
  233. }
  234. return ret;
  235. }
  236. void LLQueryResponder::queryResult(const char *buf, size_t len)
  237. {
  238. const char *pos = buf;
  239. int qdcount = DNS_HEADER_QDCOUNT(pos);
  240. int ancount = DNS_HEADER_ANCOUNT(pos);
  241. int nscount = DNS_HEADER_NSCOUNT(pos);
  242. int arcount = DNS_HEADER_ARCOUNT(pos);
  243. int ret;
  244. if (qdcount == 0 || ancount + nscount + arcount == 0)
  245. {
  246. ret = ARES_ENODATA;
  247. goto bail;
  248. }
  249. pos += NS_HFIXEDSZ;
  250. for (int i = 0; i < qdcount; i++)
  251. {
  252. std::string ignore;
  253. size_t enclen;
  254. ret = LLAres::expandName(pos, buf, len, i == 0 ? mQuery : ignore,
  255.  enclen);
  256. if (ret != ARES_SUCCESS)
  257. {
  258. goto bail;
  259. }
  260. pos += enclen;
  261. if (i == 0)
  262. {
  263. int t = DNS_QUESTION_TYPE(pos);
  264. switch (t)
  265. {
  266. case RES_A:
  267. case RES_NS:
  268. case RES_CNAME:
  269. case RES_PTR:
  270. case RES_AAAA:
  271. case RES_SRV:
  272. mType = (LLResType) t;
  273. break;
  274. default:
  275. llinfos << "Cannot grok query type " << t << llendl;
  276. ret = ARES_EBADQUERY;
  277. goto bail;
  278. }
  279. }
  280. pos += NS_QFIXEDSZ;
  281. if (pos > buf + len)
  282. {
  283. ret = ARES_EBADRESP;
  284. goto bail;
  285. }
  286. }
  287. ret = parseSection(buf, len, ancount, pos, mAnswers);
  288. if (ret != ARES_SUCCESS)
  289. {
  290. goto bail;
  291. }
  292. ret = parseSection(buf, len, nscount, pos, mAuthorities);
  293. if (ret != ARES_SUCCESS)
  294. {
  295. goto bail;
  296. }
  297. ret = parseSection(buf, len, arcount, pos, mAdditional);
  298. bail:
  299. mResult = ret;
  300. if (mResult == ARES_SUCCESS)
  301. {
  302. querySuccess();
  303. } else {
  304. queryError(mResult);
  305. }
  306. }
  307. void LLQueryResponder::querySuccess()
  308. {
  309. llinfos << "LLQueryResponder::queryResult not implemented" << llendl;
  310. }
  311. void LLAres::SrvResponder::querySuccess()
  312. {
  313. if (mType == RES_SRV)
  314. {
  315. srvResult(mAnswers);
  316. } else {
  317. srvError(ARES_EBADRESP);
  318. }
  319. }
  320. void LLAres::SrvResponder::queryError(int code)
  321. {
  322. srvError(code);
  323. }
  324. void LLAres::SrvResponder::srvResult(const dns_rrs_t &ents)
  325. {
  326. llinfos << "LLAres::SrvResponder::srvResult not implemented" << llendl;
  327. for (size_t i = 0; i < ents.size(); i++)
  328. {
  329. const LLSrvRecord *s = (const LLSrvRecord *) ents[i].get();
  330. llinfos << "[" << i << "] " << s->host() << ":" << s->port()
  331. << " priority " << s->priority()
  332. << " weight " << s->weight()
  333. << llendl;
  334. }
  335. }
  336. void LLAres::SrvResponder::srvError(int code)
  337. {
  338. llinfos << "LLAres::SrvResponder::srvError " << code << ": "
  339. << LLAres::strerror(code) << llendl;
  340. }
  341. static void nameinfo_callback_1_5(void *arg, int status, int timeouts,
  342.   char *node, char *service)
  343. {
  344. LLPointer<LLAres::NameInfoResponder> *resp =
  345. (LLPointer<LLAres::NameInfoResponder> *) arg;
  346. if (status == ARES_SUCCESS)
  347. {
  348. (*resp)->nameInfoResult(node, service);
  349. } else {
  350. (*resp)->nameInfoError(status);
  351. }
  352. delete resp;
  353. }
  354. #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
  355. static void nameinfo_callback(void *arg, int status, char *node, char *service)
  356. {
  357. nameinfo_callback_1_5(arg, status, 0, node, service);
  358. }
  359. #else
  360. # define nameinfo_callback nameinfo_callback_1_5
  361. #endif
  362. void LLAres::getNameInfo(const struct sockaddr &sa, socklen_t salen, int flags,
  363.  NameInfoResponder *resp)
  364. {
  365. ares_getnameinfo(chan_, &sa, salen, flags, nameinfo_callback,
  366.  new LLPointer<NameInfoResponder>(resp));
  367. }
  368. static void search_callback_1_5(void *arg, int status, int timeouts,
  369. unsigned char *abuf, int alen)
  370. {
  371. LLPointer<LLAres::QueryResponder> *resp =
  372. (LLPointer<LLAres::QueryResponder> *) arg;
  373. if (status == ARES_SUCCESS)
  374. {
  375. (*resp)->queryResult((const char *) abuf, alen);
  376. } else {
  377. (*resp)->queryError(status);
  378. }
  379. delete resp;
  380. }
  381. #if ARES_VERSION_MAJOR == 1 && ARES_VERSION_MINOR == 4
  382. static void search_callback(void *arg, int status, unsigned char *abuf,
  383. int alen)
  384. {
  385. search_callback_1_5(arg, status, 0, abuf, alen);
  386. }
  387. #else
  388. # define search_callback search_callback_1_5
  389. #endif
  390. void LLAres::search(const std::string &query, LLResType type,
  391. QueryResponder *resp)
  392. {
  393. ares_search(chan_, query.c_str(), ns_c_in, type, search_callback,
  394. new LLPointer<QueryResponder>(resp));
  395. }
  396. bool LLAres::process(U64 timeout)
  397. {
  398. if (!gAPRPoolp)
  399. {
  400. ll_init_apr();
  401. }
  402. int socks[ARES_GETSOCK_MAXNUM];
  403. apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
  404. apr_int32_t nsds = 0;
  405. int nactive = 0;
  406. int bitmask;
  407. bitmask = ares_getsock(chan_, socks, ARES_GETSOCK_MAXNUM);
  408. if (bitmask == 0)
  409. {
  410. return nsds > 0;
  411. }
  412. apr_status_t status;
  413. LLAPRPool pool;
  414. status = pool.getStatus() ;
  415. ll_apr_assert_status(status);
  416. for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
  417. {
  418. if (ARES_GETSOCK_READABLE(bitmask, i))
  419. {
  420. aprFds[nactive].reqevents = APR_POLLIN | APR_POLLERR;
  421. }
  422. else if (ARES_GETSOCK_WRITABLE(bitmask, i))
  423. {
  424. aprFds[nactive].reqevents = APR_POLLOUT | APR_POLLERR;
  425. } else {
  426. continue;
  427. }
  428. apr_socket_t *aprSock = NULL;
  429. status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool());
  430. if (status != APR_SUCCESS)
  431. {
  432. ll_apr_warn_status(status);
  433. return nsds > 0;
  434. }
  435. aprFds[nactive].desc.s = aprSock;
  436. aprFds[nactive].desc_type = APR_POLL_SOCKET;
  437. aprFds[nactive].p = pool.getAPRPool();
  438. aprFds[nactive].rtnevents = 0;
  439. aprFds[nactive].client_data = &socks[i];
  440. nactive++;
  441. }
  442. if (nactive > 0)
  443. {
  444. status = apr_poll(aprFds, nactive, &nsds, timeout);
  445. if (status != APR_SUCCESS && status != APR_TIMEUP)
  446. {
  447. ll_apr_warn_status(status);
  448. }
  449. for (int i = 0; i < nactive; i++)
  450. {
  451. int evts = aprFds[i].rtnevents;
  452. int ifd = (evts & (APR_POLLIN | APR_POLLERR))
  453. ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
  454. int ofd = (evts & (APR_POLLOUT | APR_POLLERR))
  455. ? *((int *) aprFds[i].client_data) : ARES_SOCKET_BAD;
  456. ares_process_fd(chan_, ifd, ofd);
  457. }
  458. }
  459. return nsds > 0;
  460. }
  461. bool LLAres::processAll()
  462. {
  463. bool anyProcessed = false, ret;
  464. do {
  465. timeval tv;
  466. ret = ares_timeout(chan_, NULL, &tv) != NULL;
  467. if (ret)
  468. {
  469. ret = process(tv.tv_sec * 1000000LL + tv.tv_usec);
  470. anyProcessed |= ret;
  471. }
  472. } while (ret);
  473. return anyProcessed;
  474. }
  475. int LLAres::expandName(const char *encoded, const char *abuf, size_t alen,
  476.    std::string &s, size_t &enclen)
  477. {
  478. char *t;
  479. int ret;
  480. long e;
  481. ret = ares_expand_name((const unsigned char *) encoded,
  482.    (const unsigned char *) abuf, alen, &t, &e);
  483. if (ret == ARES_SUCCESS)
  484. {
  485. s.assign(t);
  486. enclen = e;
  487. ares_free_string(t);
  488. }
  489. return ret;
  490. }
  491. const char *LLAres::strerror(int code)
  492. {
  493. return ares_strerror(code);
  494. }
  495. LLAres *gAres;
  496. LLAres *ll_init_ares()
  497. {
  498. if (gAres == NULL)
  499. {
  500. gAres = new LLAres();
  501. }
  502. return gAres;
  503. }
  504. LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
  505.  unsigned ttl)
  506. : LLRefCount(),
  507.   mType(type),
  508.   mName(name),
  509.   mTTL(ttl)
  510. {
  511. }
  512. LLHostRecord::LLHostRecord(LLResType type, const std::string &name,
  513.    unsigned ttl)
  514. : LLDnsRecord(type, name, ttl)
  515. {
  516. }
  517. int LLHostRecord::parse(const char *buf, size_t len, const char *pos,
  518. size_t rrlen)
  519. {
  520. int ret;
  521. ret = LLAres::expandName(pos, buf, len, mHost);
  522. if (ret != ARES_SUCCESS)
  523. {
  524. goto bail;
  525. }
  526. ret = ARES_SUCCESS;
  527. bail:
  528. return ret;
  529. }
  530. LLCnameRecord::LLCnameRecord(const std::string &name, unsigned ttl)
  531. : LLHostRecord(RES_CNAME, name, ttl)
  532. {
  533. }
  534. LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl)
  535. : LLHostRecord(RES_PTR, name, ttl)
  536. {
  537. }
  538. LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name,
  539.    unsigned ttl)
  540. : LLDnsRecord(type, name, ttl),
  541.   mSize(0)
  542. {
  543. }
  544. LLARecord::LLARecord(const std::string &name, unsigned ttl)
  545. : LLAddrRecord(RES_A, name, ttl)
  546. {
  547. }
  548. int LLARecord::parse(const char *buf, size_t len, const char *pos,
  549.  size_t rrlen)
  550. {
  551. int ret;
  552. if (rrlen != sizeof(mSA.sin.sin_addr.s_addr))
  553. {
  554. ret = ARES_EBADRESP;
  555. goto bail;
  556. }
  557. memset(&mSA, 0, sizeof(mSA));
  558. memcpy(&mSA.sin.sin_addr.s_addr, pos, rrlen);
  559. mSA.sin.sin_family = AF_INET6;
  560. mSize = sizeof(mSA.sin);
  561. ret = ARES_SUCCESS;
  562. bail:
  563. return ret;
  564. }
  565. LLAaaaRecord::LLAaaaRecord(const std::string &name, unsigned ttl)
  566. : LLAddrRecord(RES_AAAA, name, ttl)
  567. {
  568. }
  569. int LLAaaaRecord::parse(const char *buf, size_t len, const char *pos,
  570. size_t rrlen)
  571. {
  572. int ret;
  573. if (rrlen != sizeof(mSA.sin6.sin6_addr))
  574. {
  575. ret = ARES_EBADRESP;
  576. goto bail;
  577. }
  578. memset(&mSA, 0, sizeof(mSA));
  579. memcpy(&mSA.sin6.sin6_addr.s6_addr, pos, rrlen);
  580. mSA.sin6.sin6_family = AF_INET6;
  581. mSize = sizeof(mSA.sin6);
  582. ret = ARES_SUCCESS;
  583. bail:
  584. return ret;
  585. }
  586. LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl)
  587. : LLHostRecord(RES_SRV, name, ttl),
  588.   mPriority(0),
  589.   mWeight(0),
  590.   mPort(0)
  591. {
  592. }
  593. int LLSrvRecord::parse(const char *buf, size_t len, const char *pos,
  594.    size_t rrlen)
  595. {
  596. int ret;
  597. if (rrlen < 6)
  598. {
  599. ret = ARES_EBADRESP;
  600. goto bail;
  601. }
  602. memcpy(&mPriority, pos, 2);
  603. memcpy(&mWeight, pos + 2, 2);
  604. memcpy(&mPort, pos + 4, 2);
  605. mPriority = ntohs(mPriority);
  606. mWeight = ntohs(mWeight);
  607. mPort = ntohs(mPort);
  608. ret = LLHostRecord::parse(buf, len, pos + 6, rrlen - 6);
  609. bail:
  610. return ret;
  611. }
  612. LLNsRecord::LLNsRecord(const std::string &name, unsigned ttl)
  613. : LLHostRecord(RES_NS, name, ttl)
  614. {
  615. }
  616. void LLAres::UriRewriteResponder::queryError(int code)
  617. {
  618. std::vector<std::string> uris;
  619. uris.push_back(mUri.asString());
  620. rewriteResult(uris);
  621. }
  622. void LLAres::UriRewriteResponder::querySuccess()
  623. {
  624. std::vector<std::string> uris;
  625. if (mType != RES_SRV)
  626. {
  627. goto bail;
  628. }
  629. for (size_t i = 0; i < mAnswers.size(); i++)
  630. {
  631. const LLSrvRecord *r = (const LLSrvRecord *) mAnswers[i].get();
  632. if (r->type() == RES_SRV)
  633. {
  634. // Check the domain in the response to ensure that it's
  635. // the same as the domain in the request, so that bad guys
  636. // can't forge responses that point to their own login
  637. // servers with their own certificates.
  638. // Hard-coding the domain to check here is a bit of a
  639. // hack.  Hoist it to an outer caller if anyone ever needs
  640. // this functionality on other domains.
  641. static const std::string domain(".lindenlab.com");
  642. const std::string &host = r->host();
  643. std::string::size_type s = host.find(domain) + domain.length();
  644. if (s != host.length() && s != host.length() - 1)
  645. {
  646. continue;
  647. }
  648. LLURI uri(mUri.scheme(),
  649.   mUri.userName(),
  650.   mUri.password(),
  651.   r->host(),
  652.   mUri.defaultPort() ? r->port() : mUri.hostPort(),
  653.   mUri.escapedPath(),
  654.   mUri.escapedQuery());
  655. uris.push_back(uri.asString());
  656. }
  657. }
  658. if (!uris.empty())
  659. {
  660. goto done;
  661. }
  662. bail:
  663. uris.push_back(mUri.asString());
  664. done:
  665. rewriteResult(uris);
  666. }
  667. void LLAres::UriRewriteResponder::rewriteResult(
  668. const std::vector<std::string> &uris)
  669. {
  670. llinfos << "LLAres::UriRewriteResponder::rewriteResult not implemented"
  671. << llendl;
  672. for (size_t i = 0; i < uris.size(); i++)
  673. {
  674. llinfos << "[" << i << "] " << uris[i] << llendl;
  675. }
  676. }