Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1197 lines
31 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. caddrlst.cxx
  5. Abstract:
  6. Contains CAddressList class definition
  7. Contents:
  8. CAddressList::FreeList
  9. CAddressList::SetList
  10. CAddressList::SetList
  11. CAddressList::GetNextAddress
  12. CAddressList::InvalidateAddress
  13. CAddressList::ResolveHost
  14. CFsm_ResolveHost::RunSM
  15. (CAddressList::IPAddressToAddressList)
  16. (CAddressList::HostentToAddressList)
  17. Author:
  18. Richard L Firth (rfirth) 19-Apr-1997
  19. Environment:
  20. Win32 user-mode DLL
  21. Revision History:
  22. 19-Apr-1997 rfirth
  23. Created
  24. 28-Jan-1998 rfirth
  25. No longer randomly index address list. NT5 and Win98 are modified to
  26. return the address list in decreasing order of desirability by RTT/
  27. route
  28. --*/
  29. #include <wininetp.h>
  30. #include <perfdiag.hxx>
  31. //#define TEST_CODE
  32. //Thread-procedure for async gethostbyname
  33. DWORD WINAPI AsyncGetHostByName(LPVOID lpParameter);
  34. //The destructor is called only when all refcounts have dropped to 0.
  35. // i.e. when the INTERNET_HANDLE_OBJECT has released its reference,
  36. // AND when all the GHBN threads are done.
  37. // At this point, we can flush the hostent cache and terminate list.
  38. CResolverCache::~CResolverCache()
  39. {
  40. FlushHostentCache(&_ResolverCache);
  41. TerminateSerializedList(&_ResolverCache);
  42. if (_pHandlesList)
  43. delete _pHandlesList;
  44. }
  45. void CResolverCache::ForceEmptyAndDeleteHandlesList()
  46. {
  47. INET_ASSERT(_pHandlesList);
  48. _pHandlesList->LockList();
  49. CListItem* pItem = _pHandlesList->GetHead();
  50. while(pItem)
  51. {
  52. CListItem* pNext = pItem->GetNext();
  53. (((CGetHostItem*)pItem)->ForceDelete());
  54. delete pItem;
  55. _pHandlesList->ReduceCount();
  56. pItem = pNext;
  57. }
  58. //it's not going to be reused after this, so head and tail don't have to be set to NULL
  59. // on _pHandlesList
  60. _pHandlesList->UnlockList();
  61. }
  62. void CResolverCache::EmptyHandlesList()
  63. {
  64. if (_pHandlesList)
  65. {
  66. _pHandlesList->LockList();
  67. CListItem* pItem = _pHandlesList->GetHead();
  68. while(pItem)
  69. {
  70. CListItem* pNext = pItem->GetNext();
  71. (((CGetHostItem*)pItem)->WaitDelete());
  72. delete pItem;
  73. _pHandlesList->ReduceCount();
  74. pItem = pNext;
  75. }
  76. //it's not going to be reused after this, so head and tail don't have to be set to NULL
  77. // on _pHandlesList
  78. _pHandlesList->UnlockList();
  79. }
  80. }
  81. void CResolverCache::TrimHandlesListSize(ULONG nTrimSize)
  82. {
  83. _pHandlesList->LockList();
  84. if (_pHandlesList->GetCount() >= nTrimSize)
  85. {
  86. CListItem* pItem = _pHandlesList->GetHead();
  87. CListItem* pPrev = NULL;
  88. while(pItem)
  89. {
  90. CListItem* pNext = pItem->GetNext();
  91. if (((CGetHostItem*)pItem)->CanBeDeleted())
  92. {
  93. if (pPrev)
  94. {
  95. pPrev->SetNext(pNext);
  96. }
  97. else
  98. {
  99. //The item being removed WAS the head.
  100. _pHandlesList->SetHead(pNext);
  101. }
  102. if (!pNext)
  103. {
  104. //The item being removed WAS the tail.
  105. _pHandlesList->SetTail(pPrev);
  106. }
  107. delete pItem;
  108. _pHandlesList->ReduceCount();
  109. }
  110. else
  111. {
  112. pPrev = pItem;
  113. }
  114. pItem = pNext;
  115. }
  116. }
  117. _pHandlesList->UnlockList();
  118. }
  119. BOOL CResolverCache::AddToHandlesList(HANDLE hThread, CGetHostItem* pGetHostItem)
  120. {
  121. BOOL bRetval = TRUE;
  122. INET_ASSERT(_pHandlesList);
  123. pGetHostItem->SetThreadHandle(hThread);
  124. TrimHandlesListSize();
  125. _pHandlesList->AddToTail(pGetHostItem);
  126. return bRetval;
  127. }
  128. DWORD WINAPI AsyncGetHostByName(LPVOID lpParameter)
  129. {
  130. #ifdef WINHTTP_FOR_MSXML
  131. //
  132. // MSXML needs to initialize is thread local storage data.
  133. // It does not do this during DLL_THREAD_ATTACH, so our
  134. // worker thread must explicitly call into MSXML to initialize
  135. // its TLS for this thread.
  136. //
  137. InitializeMsxmlTLS();
  138. #endif
  139. CGetHostItem* pGetHostItem = (CGetHostItem*)lpParameter;
  140. LPSTR lpszHostName = pGetHostItem->GetHostName();
  141. LPHOSTENT lpHostEnt;
  142. DWORD dwError = 0;
  143. if (!(lpHostEnt = _I_gethostbyname(lpszHostName)))
  144. {
  145. dwError = _I_WSAGetLastError();
  146. }
  147. else
  148. {
  149. VOID* pAlloc = pGetHostItem->GetAllocPointer();
  150. CacheHostent((pGetHostItem->GetResolverCache())->GetResolverCacheList(), lpszHostName, lpHostEnt, LIVE_DEFAULT, &pAlloc, pGetHostItem->GetAllocSize());
  151. if (pAlloc)
  152. {
  153. //pAlloc is overwritten to NULL in CacheHostent if the memory is used,
  154. //we need to delete the alloced memory only if non-NULL
  155. pGetHostItem->SetDelete();
  156. }
  157. }
  158. return dwError;
  159. }
  160. //
  161. // methods
  162. //
  163. VOID
  164. CAddressList::FreeList(
  165. VOID
  166. )
  167. /*++
  168. Routine Description:
  169. Free address list
  170. Arguments:
  171. None.
  172. Return Value:
  173. None.
  174. --*/
  175. {
  176. if (m_Addresses != NULL) {
  177. m_Addresses = (LPRESOLVED_ADDRESS)FREE_MEMORY((HLOCAL)m_Addresses);
  178. INET_ASSERT(m_Addresses == NULL);
  179. m_AddressCount = 0;
  180. m_BadAddressCount = 0;
  181. m_CurrentAddress = 0;
  182. }
  183. }
  184. DWORD
  185. CAddressList::SetList(
  186. IN DWORD dwIpAddress
  187. )
  188. /*++
  189. Routine Description:
  190. Sets the list contents from the IP address
  191. Arguments:
  192. dwIpAddress - IP address from which to create list contents
  193. Return Value:
  194. DWORD
  195. Success - ERROR_SUCCESS
  196. Failure - ERROR_NOT_ENOUGH_MEMORY
  197. --*/
  198. {
  199. if (!Acquire())
  200. {
  201. return ERROR_NOT_ENOUGH_MEMORY;
  202. }
  203. FreeList();
  204. DWORD error = IPAddressToAddressList(dwIpAddress);
  205. Release();
  206. return error;
  207. }
  208. DWORD
  209. CAddressList::SetList(
  210. IN LPHOSTENT lpHostent
  211. )
  212. /*++
  213. Routine Description:
  214. Sets the list contents from the hostent
  215. Arguments:
  216. lpHostent - pointer to hostent containing resolved addresses to add
  217. Return Value:
  218. DWORD
  219. Success - ERROR_SUCCESS
  220. Failure - ERROR_NOT_ENOUGH_MEMORY
  221. --*/
  222. {
  223. if (!Acquire())
  224. {
  225. return ERROR_NOT_ENOUGH_MEMORY;
  226. }
  227. FreeList();
  228. DWORD error = HostentToAddressList(lpHostent);
  229. Release();
  230. return error;
  231. }
  232. BOOL
  233. CAddressList::GetNextAddress(
  234. OUT LPDWORD lpdwResolutionId,
  235. IN OUT LPDWORD lpdwIndex,
  236. IN INTERNET_PORT nPort,
  237. OUT LPCSADDR_INFO lpAddressInfo
  238. )
  239. /*++
  240. Routine Description:
  241. Get next address to use when connecting. If we already have a preferred
  242. address, use that. We make a copy of the address to use in the caller's
  243. data space
  244. Arguments:
  245. lpdwResolutionId - used to determine whether the address list has been
  246. resolved between calls
  247. lpdwIndex - IN: current index tried; -1 if we want to try default
  248. OUT: index of address address returned if successful
  249. nPort - which port we want to connect to
  250. lpAddressInfo - pointer to returned address if successful
  251. Return Value:
  252. BOOL
  253. TRUE - lpResolvedAddress contains resolved address to use
  254. FALSE - need to (re-)resolve name
  255. --*/
  256. {
  257. DEBUG_ENTER((DBG_SOCKETS,
  258. Bool,
  259. "CAddressList::GetNextAddress",
  260. "%#x [%d], %#x [%d], %d, %#x",
  261. lpdwResolutionId,
  262. *lpdwResolutionId,
  263. lpdwIndex,
  264. *lpdwIndex,
  265. nPort,
  266. lpAddressInfo
  267. ));
  268. PERF_ENTER(GetNextAddress);
  269. BOOL bOk = TRUE;
  270. //
  271. // if we tried all the addresses and failed already, re-resolve the name
  272. //
  273. if (!Acquire())
  274. {
  275. bOk = FALSE;
  276. goto quit;
  277. }
  278. if (m_BadAddressCount < m_AddressCount) {
  279. if (*lpdwIndex != (DWORD)-1) {
  280. INET_ASSERT(m_BadAddressCount < m_AddressCount);
  281. INT i = 0;
  282. m_CurrentAddress = *lpdwIndex;
  283. INET_ASSERT((m_CurrentAddress >= 0)
  284. && (m_CurrentAddress < m_AddressCount));
  285. if ((m_CurrentAddress < 0) || (m_CurrentAddress >= m_AddressCount)) {
  286. m_CurrentAddress = 0;
  287. }
  288. do {
  289. NextAddress();
  290. if (++i == m_AddressCount) {
  291. bOk = FALSE;
  292. break;
  293. }
  294. } while (!IsCurrentAddressValid());
  295. }
  296. //
  297. // check to make sure this address hasn't expired
  298. //
  299. //if (!CheckHostentCacheTtl()) {
  300. // bOk = FALSE;
  301. //}
  302. } else {
  303. DEBUG_PRINT(SOCKETS,
  304. INFO,
  305. ("exhausted %d addresses\n",
  306. m_BadAddressCount
  307. ));
  308. bOk = FALSE;
  309. }
  310. if (bOk) {
  311. DWORD dwLocalLength = LocalSockaddrLength();
  312. LPBYTE lpRemoteAddr = (LPBYTE)(lpAddressInfo + 1) + dwLocalLength;
  313. memcpy(lpAddressInfo + 1, LocalSockaddr(), dwLocalLength);
  314. memcpy(lpRemoteAddr, RemoteSockaddr(), RemoteSockaddrLength());
  315. lpAddressInfo->LocalAddr.lpSockaddr = (LPSOCKADDR)(lpAddressInfo + 1);
  316. lpAddressInfo->LocalAddr.iSockaddrLength = dwLocalLength;
  317. lpAddressInfo->RemoteAddr.lpSockaddr = (LPSOCKADDR)lpRemoteAddr;
  318. lpAddressInfo->RemoteAddr.iSockaddrLength = RemoteSockaddrLength();
  319. lpAddressInfo->iSocketType = SocketType();
  320. lpAddressInfo->iProtocol = Protocol();
  321. ((LPSOCKADDR_IN)lpAddressInfo->RemoteAddr.lpSockaddr)->sin_port =
  322. _I_htons((unsigned short)nPort);
  323. *lpdwIndex = m_CurrentAddress;
  324. DEBUG_PRINT(SOCKETS,
  325. INFO,
  326. ("current address = %d.%d.%d.%d\n",
  327. ((LPBYTE)RemoteSockaddr())[4] & 0xff,
  328. ((LPBYTE)RemoteSockaddr())[5] & 0xff,
  329. ((LPBYTE)RemoteSockaddr())[6] & 0xff,
  330. ((LPBYTE)RemoteSockaddr())[7] & 0xff
  331. ));
  332. //dprintf("returning address %d.%d.%d.%d, index %d:%d\n",
  333. // ((LPBYTE)RemoteSockaddr())[4] & 0xff,
  334. // ((LPBYTE)RemoteSockaddr())[5] & 0xff,
  335. // ((LPBYTE)RemoteSockaddr())[6] & 0xff,
  336. // ((LPBYTE)RemoteSockaddr())[7] & 0xff,
  337. // m_ResolutionId,
  338. // m_CurrentAddress
  339. // );
  340. }
  341. *lpdwResolutionId = m_ResolutionId;
  342. DEBUG_PRINT(SOCKETS,
  343. INFO,
  344. ("ResolutionId = %d, Index = %d\n",
  345. m_ResolutionId,
  346. m_CurrentAddress
  347. ));
  348. Release();
  349. quit:
  350. PERF_LEAVE(GetNextAddress);
  351. DEBUG_LEAVE(bOk);
  352. return bOk;
  353. }
  354. VOID
  355. CAddressList::InvalidateAddress(
  356. IN DWORD dwResolutionId,
  357. IN DWORD dwAddressIndex
  358. )
  359. /*++
  360. Routine Description:
  361. We failed to create a connection. Invalidate the address so other requests
  362. will try another address
  363. Arguments:
  364. dwResolutionId - used to ensure coherency of address list
  365. dwAddressIndex - which address to invalidate
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. DEBUG_ENTER((DBG_SOCKETS,
  371. None,
  372. "CAddressList::InvalidateAddress",
  373. "%d, %d",
  374. dwResolutionId,
  375. dwAddressIndex
  376. ));
  377. //dprintf("invalidating %d.%d.%d.%d, index %d:%d\n",
  378. // ((LPBYTE)RemoteSockaddr())[4] & 0xff,
  379. // ((LPBYTE)RemoteSockaddr())[5] & 0xff,
  380. // ((LPBYTE)RemoteSockaddr())[6] & 0xff,
  381. // ((LPBYTE)RemoteSockaddr())[7] & 0xff,
  382. // dwResolutionId,
  383. // dwAddressIndex
  384. // );
  385. if (!Acquire())
  386. goto quit; // just take the hit of trying again, if we can.
  387. //
  388. // only do this if the list is the same age as when the caller last tried
  389. // an address
  390. //
  391. if (dwResolutionId == m_ResolutionId) {
  392. INET_ASSERT(((INT)dwAddressIndex >= 0)
  393. && ((INT)dwAddressIndex < m_AddressCount));
  394. if (dwAddressIndex < (DWORD)m_AddressCount) {
  395. m_Addresses[dwAddressIndex].IsValid = FALSE;
  396. DEBUG_PRINT(SOCKETS,
  397. INFO,
  398. ("invalidated address %d.%d.%d.%d\n",
  399. ((LPBYTE)RemoteSockaddr())[4] & 0xff,
  400. ((LPBYTE)RemoteSockaddr())[5] & 0xff,
  401. ((LPBYTE)RemoteSockaddr())[6] & 0xff,
  402. ((LPBYTE)RemoteSockaddr())[7] & 0xff
  403. ));
  404. INET_ASSERT(m_BadAddressCount <= m_AddressCount);
  405. if (m_BadAddressCount < m_AddressCount) {
  406. ++m_BadAddressCount;
  407. if (m_BadAddressCount < m_AddressCount) {
  408. for (int i = 0;
  409. !IsCurrentAddressValid() && (i < m_AddressCount);
  410. ++i) {
  411. NextAddress();
  412. }
  413. }
  414. }
  415. }
  416. }
  417. Release();
  418. quit:
  419. DEBUG_LEAVE(0);
  420. }
  421. DWORD
  422. CAddressList::ResolveHost(
  423. IN LPSTR lpszHostName,
  424. IN OUT LPDWORD lpdwResolutionId,
  425. IN DWORD dwFlags
  426. )
  427. /*++
  428. Routine Description:
  429. Resolves host name (or (IP-)address)
  430. BUGBUG: Ideally, we don't want to keep hold of worker threads if we are in
  431. the blocking gethostbyname() call. But correctly handling this is
  432. difficult, so we always block the thread while we are resolving.
  433. For this reason, an async request being run on an app thread should
  434. have switched to a worker thread before calling this function.
  435. Arguments:
  436. lpszHostName - host name (or IP-address) to resolve
  437. lpdwResolutionId - used to determine whether entry changed
  438. dwFlags - controlling request:
  439. SF_INDICATE - if set, make indications via callback
  440. SF_FORCE - if set, force (re-)resolve
  441. Return Value:
  442. DWORD
  443. Success - ERROR_SUCCESS
  444. Name successfully resolved
  445. Failure - ERROR_WINHTTP_NAME_NOT_RESOLVED
  446. Couldn't resolve the name
  447. ERROR_NOT_ENOUGH_MEMORY
  448. Couldn't allocate memory for the FSM
  449. --*/
  450. {
  451. DEBUG_ENTER((DBG_SOCKETS,
  452. Dword,
  453. "CAddressList::ResolveHost",
  454. "%q, %d, %#x",
  455. lpszHostName,
  456. *lpdwResolutionId,
  457. dwFlags
  458. ));
  459. DWORD error;
  460. error = DoFsm(New CFsm_ResolveHost(lpszHostName,
  461. lpdwResolutionId,
  462. dwFlags,
  463. this
  464. ));
  465. //quit:
  466. DEBUG_LEAVE(error);
  467. return error;
  468. }
  469. DWORD
  470. CFsm_ResolveHost::RunSM(
  471. IN CFsm * Fsm
  472. )
  473. {
  474. DEBUG_ENTER((DBG_SESSION,
  475. Dword,
  476. "CFsm_ResolveHost::RunSM",
  477. "%#x",
  478. Fsm
  479. ));
  480. CAddressList * pAddressList = (CAddressList *)Fsm->GetContext();
  481. CFsm_ResolveHost * stateMachine = (CFsm_ResolveHost *)Fsm;
  482. DWORD error;
  483. switch (Fsm->GetState()) {
  484. case FSM_STATE_INIT:
  485. case FSM_STATE_CONTINUE:
  486. error = pAddressList->ResolveHost_Fsm(stateMachine);
  487. break;
  488. case FSM_STATE_ERROR:
  489. error = Fsm->GetError();
  490. Fsm->SetDone();
  491. break;
  492. default:
  493. error = ERROR_WINHTTP_INTERNAL_ERROR;
  494. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  495. INET_ASSERT(FALSE);
  496. break;
  497. }
  498. DEBUG_LEAVE(error);
  499. return error;
  500. }
  501. DWORD
  502. CAddressList::ResolveHost_Fsm(
  503. IN CFsm_ResolveHost * Fsm
  504. )
  505. {
  506. DEBUG_ENTER((DBG_SOCKETS,
  507. Dword,
  508. "CAddressList::ResolveHost_Fsm",
  509. "%#x(%q, %#x [%d], %#x)",
  510. Fsm,
  511. Fsm->m_lpszHostName,
  512. Fsm->m_lpdwResolutionId,
  513. *Fsm->m_lpdwResolutionId,
  514. Fsm->m_dwFlags
  515. ));
  516. PERF_ENTER(ResolveHost);
  517. //
  518. // restore variables from FSM object
  519. //
  520. CFsm_ResolveHost & fsm = *Fsm;
  521. LPSTR lpszHostName = fsm.m_lpszHostName;
  522. LPDWORD lpdwResolutionId = fsm.m_lpdwResolutionId;
  523. DWORD dwFlags = fsm.m_dwFlags;
  524. LPINTERNET_THREAD_INFO lpThreadInfo = fsm.GetThreadInfo();
  525. INTERNET_HANDLE_BASE * pHandle = fsm.GetMappedHandleObject();
  526. DWORD error = ERROR_SUCCESS;
  527. CResolverCache* pResolverCache = GetRootHandle(pHandle)->GetResolverCache();
  528. DWORD dwWaitTime;
  529. LPHOSTENT lpHostent = NULL;
  530. DWORD ttl;
  531. //
  532. // BUGBUG - RLF 04/23/97
  533. //
  534. // This is sub-optimal. We want to block worker FSMs and free up the worker
  535. // thread. Sync client threads can wait. However, since a clash is not very
  536. // likely, we'll block all threads for now and come up with a better
  537. // solution later (XTLock).
  538. //
  539. // Don't have time to implement the proper solution now
  540. //
  541. if (!Acquire())
  542. {
  543. error = ERROR_NOT_ENOUGH_MEMORY;
  544. goto exit;
  545. }
  546. //
  547. // if the resolution id is different then the name has already been resolved
  548. //
  549. if (*lpdwResolutionId != m_ResolutionId)
  550. {
  551. goto done;
  552. }
  553. //
  554. // if we're an app thread making an async request then go async now rather
  555. // than risk blocking the app thread. This will be the typical scenario for
  556. // IE, and we care about little else
  557. //
  558. // BUGBUG - RLF 05/20/97
  559. //
  560. // We should really lock & test the cache first, but let's do that after
  561. // Beta2 (its perf work)
  562. //
  563. // It cannot happen that this condition be true.
  564. // WinHttpSendRequest would have queued an async fsm if it was async to begin with.
  565. INET_ASSERT(lpThreadInfo->IsAsyncWorkerThread
  566. || !pHandle->IsAsyncHandle());
  567. /*
  568. if (!lpThreadInfo->IsAsyncWorkerThread
  569. && pHandle->IsAsyncHandle()
  570. && (fsm.GetAppContext() != NULL))
  571. {
  572. DEBUG_PRINT(SOCKETS,
  573. INFO,
  574. ("async request on app thread - jumping to hyper-drive\n"
  575. ));
  576. error = Fsm->QueueWorkItem();
  577. goto done;
  578. }
  579. */
  580. //
  581. // throw out current list (if any)
  582. //
  583. FreeList();
  584. //
  585. // let the app know we are resolving the name
  586. //
  587. if (dwFlags & SF_INDICATE)
  588. {
  589. error = InternetIndicateStatusString(WINHTTP_CALLBACK_STATUS_RESOLVING_NAME,
  590. lpszHostName,
  591. TRUE/*bCopyBuffer*/
  592. );
  593. //bail out if aborted before network operation.
  594. if (error != ERROR_SUCCESS)
  595. {
  596. INET_ASSERT(error == ERROR_WINHTTP_OPERATION_CANCELLED);
  597. goto done;
  598. }
  599. }
  600. //
  601. // figure out if we're being asked to resolve a name or an address. If
  602. // inet_addr() succeeds then we were given a string representation of an
  603. // address
  604. //
  605. DWORD ipAddr;
  606. //dprintf("resolving %q\n", lpszHostName);
  607. ipAddr = _I_inet_addr(lpszHostName);
  608. if (ipAddr != INADDR_NONE)
  609. {
  610. //
  611. // IP address was passed in. Simply convert to address list and quit
  612. //
  613. error = SetList(ipAddr);
  614. goto quit;
  615. }
  616. //
  617. // 255.255.255.255 (or 65535.65535 or 16777215.255) would never work anyway
  618. //
  619. INET_ASSERT(lstrcmp(lpszHostName, "255.255.255.255"));
  620. //
  621. // now try to find the name or address in the cache. If it's not in the
  622. // cache then resolve it
  623. //
  624. if (!(dwFlags & SF_FORCE)
  625. && QueryHostentCache(pResolverCache->GetResolverCacheList(), lpszHostName, NULL, &lpHostent, &ttl))
  626. {
  627. error = SetList(lpHostent);
  628. ReleaseHostentCacheEntry(pResolverCache->GetResolverCacheList(), lpHostent);
  629. ++m_ResolutionId;
  630. goto quit;
  631. }
  632. //
  633. // if we call winsock gethostbyname() then we don't get to find out the
  634. // time-to-live as returned by DNS, so we have to use the default value
  635. // (LIVE_DEFAULT)
  636. //
  637. dwWaitTime = GetTimeoutValue(WINHTTP_OPTION_RESOLVE_TIMEOUT);
  638. // if a resolve timeout is specified by the application, then honor it.
  639. // If anything fails in the async pathway, DON'T default to sync GHBN.
  640. if (dwWaitTime != INFINITE)
  641. {
  642. DWORD dwThreadId;
  643. LPSTR lpszCopyHostName = NewString(lpszHostName);
  644. if (lpszCopyHostName)
  645. {
  646. #define SZ_AVG_RESOLVER_ENTRY_BYTES 512
  647. VOID* pAlloc = ALLOCATE_MEMORY(LMEM_FIXED, SZ_AVG_RESOLVER_ENTRY_BYTES);
  648. CGetHostItem* pGetHostItem = New CGetHostItem(lpszCopyHostName, pResolverCache, pAlloc, pAlloc?SZ_AVG_RESOLVER_ENTRY_BYTES:0);
  649. if (!pGetHostItem)
  650. {
  651. FREE_FIXED_MEMORY(lpszCopyHostName);
  652. goto failed;
  653. }
  654. HANDLE hThread = 0;
  655. WRAP_REVERT_USER(CreateThread, (NULL, 0, &AsyncGetHostByName,
  656. pGetHostItem, 0, &dwThreadId), hThread);
  657. // HANDLE hThread = CreateThread(NULL, 0, &AsyncGetHostByName,
  658. // pGetHostItem, 0, &dwThreadId);
  659. if (!hThread)
  660. {
  661. delete pGetHostItem;
  662. goto failed;
  663. }
  664. DWORD dwWaitResponse = WaitForSingleObject(hThread, dwWaitTime);
  665. if (dwWaitResponse == WAIT_OBJECT_0)
  666. {
  667. DWORD dwError;
  668. BOOL fRet = GetExitCodeThread(hThread, &dwError); //want to use this error?
  669. INET_ASSERT(dwError != STILL_ACTIVE);
  670. if (fRet && !dwError && QueryHostentCache(pResolverCache->GetResolverCacheList(), lpszCopyHostName, NULL, &lpHostent, &ttl))
  671. {
  672. error = SetList(lpHostent);
  673. ReleaseHostentCacheEntry(pResolverCache->GetResolverCacheList(), lpHostent);
  674. ++m_ResolutionId;
  675. }
  676. CloseHandle(hThread);
  677. delete pGetHostItem;
  678. DEBUG_PRINT(SOCKETS,
  679. INFO,
  680. ("%q %sresolved\n",
  681. lpszHostName,
  682. lpHostent ? "" : "NOT "
  683. ));
  684. }
  685. else //(dwWaitResponse == WAIT_TIMEOUT)
  686. {
  687. //let thread die and if it successfully resolved host, it can add to cache.
  688. pResolverCache->AddToHandlesList(hThread, pGetHostItem);
  689. }
  690. } //lpszCopyHostName
  691. }// dwWaitTime (specified on this handle)
  692. else
  693. {
  694. //synchronous get host by name
  695. lpHostent = _I_gethostbyname(lpszHostName);
  696. DEBUG_PRINT(SOCKETS,
  697. INFO,
  698. ("%q %sresolved\n",
  699. lpszHostName,
  700. lpHostent ? "" : "NOT "
  701. ));
  702. if (lpHostent != NULL)
  703. {
  704. CacheHostent(pResolverCache->GetResolverCacheList(), lpszHostName, lpHostent, LIVE_DEFAULT);
  705. error = SetList(lpHostent);
  706. ++m_ResolutionId;
  707. }
  708. }
  709. failed:
  710. if (!lpHostent)
  711. {
  712. error = ERROR_WINHTTP_NAME_NOT_RESOLVED;
  713. }
  714. quit:
  715. if ((error == ERROR_SUCCESS) && (dwFlags & SF_INDICATE)) {
  716. //
  717. // inform the app that we have resolved the name
  718. //
  719. InternetIndicateStatusAddress(WINHTTP_CALLBACK_STATUS_NAME_RESOLVED,
  720. RemoteSockaddr(),
  721. RemoteSockaddrLength()
  722. );
  723. }
  724. *lpdwResolutionId = m_ResolutionId;
  725. done:
  726. Release();
  727. exit:
  728. if (error != ERROR_IO_PENDING) {
  729. fsm.SetDone();
  730. //PERF_LEAVE(ResolveHost);
  731. }
  732. PERF_LEAVE(ResolveHost);
  733. DEBUG_LEAVE(error);
  734. return error;
  735. }
  736. //
  737. // private methods
  738. //
  739. PRIVATE
  740. DWORD
  741. CAddressList::IPAddressToAddressList(
  742. IN DWORD ipAddr
  743. )
  744. /*++
  745. Routine Description:
  746. Converts an IP-address to a RESOLVED_ADDRESS
  747. Arguments:
  748. ipAddr - IP address to convert
  749. Return Value:
  750. DWORD
  751. Success - ERROR_SUCCESS
  752. Failure - ERROR_NOT_ENOUGH_MEMORY
  753. --*/
  754. {
  755. LPRESOLVED_ADDRESS address = (LPRESOLVED_ADDRESS)ALLOCATE_MEMORY(
  756. LMEM_FIXED,
  757. sizeof(RESOLVED_ADDRESS)
  758. //
  759. // 1 local and 1 remote
  760. // socket address
  761. //
  762. + 2 * sizeof(SOCKADDR)
  763. );
  764. if (address == NULL) {
  765. return ERROR_NOT_ENOUGH_MEMORY;
  766. }
  767. LPBYTE lpVariable;
  768. LPSOCKADDR_IN lpSin;
  769. lpVariable = (LPBYTE)address + (sizeof(RESOLVED_ADDRESS));
  770. //
  771. // for each IP address in the hostent, build a CSADDR_INFO structure:
  772. // create a local SOCKADDR containing only the address family (AF_INET),
  773. // everything else is zeroed; create a remote SOCKADDR containing the
  774. // address family (AF_INET), zero port value and the IP address
  775. // presented in the arguments
  776. //
  777. address->AddrInfo.LocalAddr.lpSockaddr = (LPSOCKADDR)lpVariable;
  778. address->AddrInfo.LocalAddr.iSockaddrLength = sizeof(SOCKADDR);
  779. lpSin = (LPSOCKADDR_IN)lpVariable;
  780. lpVariable += sizeof(*lpSin);
  781. lpSin->sin_family = AF_INET;
  782. lpSin->sin_port = 0;
  783. *(LPDWORD)&lpSin->sin_addr = INADDR_ANY;
  784. memset(lpSin->sin_zero, 0, sizeof(lpSin->sin_zero));
  785. address->AddrInfo.RemoteAddr.lpSockaddr = (LPSOCKADDR)lpVariable;
  786. address->AddrInfo.RemoteAddr.iSockaddrLength = sizeof(SOCKADDR);
  787. lpSin = (LPSOCKADDR_IN)lpVariable;
  788. lpVariable += sizeof(*lpSin);
  789. lpSin->sin_family = AF_INET;
  790. lpSin->sin_port = 0;
  791. *(LPDWORD)&lpSin->sin_addr = ipAddr;
  792. memset(lpSin->sin_zero, 0, sizeof(lpSin->sin_zero));
  793. address->AddrInfo.iSocketType = SOCK_STREAM;
  794. address->AddrInfo.iProtocol = IPPROTO_TCP;
  795. address->IsValid = TRUE;
  796. //
  797. // update the object
  798. //
  799. INET_ASSERT(m_AddressCount == 0);
  800. INET_ASSERT(m_Addresses == NULL);
  801. m_AddressCount = 1;
  802. m_BadAddressCount = 0;
  803. m_Addresses = address;
  804. m_CurrentAddress = 0; // only one to choose from
  805. return ERROR_SUCCESS;
  806. }
  807. PRIVATE
  808. DWORD
  809. CAddressList::HostentToAddressList(
  810. IN LPHOSTENT lpHostent
  811. )
  812. /*++
  813. Routine Description:
  814. Converts a HOSTENT structure to an array of RESOLVED_ADDRESSs
  815. Arguments:
  816. lpHostent - pointer to HOSTENT to convert
  817. Return Value:
  818. DWORD
  819. Success - ERROR_SUCCESS
  820. Failure - ERROR_NOT_ENOUGH_MEMORY
  821. --*/
  822. {
  823. INET_ASSERT(lpHostent != NULL);
  824. LPBYTE * addressList = (LPBYTE *)lpHostent->h_addr_list;
  825. INET_ASSERT(addressList[0]);
  826. //
  827. // first off, figure out how many addresses there are in the hostent
  828. //
  829. int nAddrs;
  830. if (fDontUseDNSLoadBalancing) {
  831. nAddrs = 1;
  832. } else {
  833. for (nAddrs = 0; addressList[nAddrs] != NULL; ++nAddrs) {
  834. /* NOTHING */
  835. }
  836. #ifdef TEST_CODE
  837. nAddrs = 4;
  838. #endif
  839. }
  840. LPRESOLVED_ADDRESS addresses = (LPRESOLVED_ADDRESS)ALLOCATE_MEMORY(
  841. LMEM_FIXED,
  842. nAddrs * (sizeof(RESOLVED_ADDRESS)
  843. //
  844. // need 1 local and 1 remote socket
  845. // address for each
  846. //
  847. + 2 * sizeof(SOCKADDR))
  848. );
  849. if (addresses == NULL) {
  850. return ERROR_NOT_ENOUGH_MEMORY;
  851. }
  852. //
  853. // for each IP address in the hostent, build a RESOLVED_ADDRESS structure:
  854. // create a local SOCKADDR containing only the address family (AF_INET),
  855. // everything else is zeroed; create a remote SOCKADDR containing the
  856. // address family (AF_INET), zero port value, and the IP address from
  857. // the hostent presented in the arguments
  858. //
  859. LPBYTE lpVariable = (LPBYTE)addresses + (nAddrs * sizeof(RESOLVED_ADDRESS));
  860. LPSOCKADDR_IN lpSin;
  861. for (int i = 0; i < nAddrs; ++i) {
  862. addresses[i].AddrInfo.LocalAddr.lpSockaddr = (LPSOCKADDR)lpVariable;
  863. addresses[i].AddrInfo.LocalAddr.iSockaddrLength = sizeof(SOCKADDR);
  864. lpSin = (LPSOCKADDR_IN)lpVariable;
  865. lpVariable += sizeof(*lpSin);
  866. lpSin->sin_family = AF_INET;
  867. lpSin->sin_port = 0;
  868. *(LPDWORD)&lpSin->sin_addr = INADDR_ANY;
  869. memset(lpSin->sin_zero, 0, sizeof(lpSin->sin_zero));
  870. addresses[i].AddrInfo.RemoteAddr.lpSockaddr = (LPSOCKADDR)lpVariable;
  871. addresses[i].AddrInfo.RemoteAddr.iSockaddrLength = sizeof(SOCKADDR);
  872. lpSin = (LPSOCKADDR_IN)lpVariable;
  873. lpVariable += sizeof(*lpSin);
  874. lpSin->sin_family = AF_INET;
  875. lpSin->sin_port = 0;
  876. #ifdef TEST_CODE
  877. //if (i) {
  878. *(LPDWORD)&lpSin->sin_addr = 0x04030201;
  879. //*(LPDWORD)&lpSin->sin_addr = 0x1cfe379d;
  880. //}
  881. #else
  882. *(LPDWORD)&lpSin->sin_addr = *(LPDWORD)addressList[i];
  883. #endif
  884. memset(lpSin->sin_zero, 0, sizeof(lpSin->sin_zero));
  885. addresses[i].AddrInfo.iSocketType = SOCK_STREAM;
  886. addresses[i].AddrInfo.iProtocol = IPPROTO_TCP;
  887. addresses[i].IsValid = TRUE;
  888. }
  889. #ifdef TEST_CODE
  890. *((LPDWORD)&((LPSOCKADDR_IN)addresses[3].AddrInfo.RemoteAddr.lpSockaddr)->sin_addr) = *(LPDWORD)addressList[0];
  891. //((LPSOCKADDR_IN)addresses[7].AddrInfo.RemoteAddr.lpSockaddr)->sin_addr = ((LPSOCKADDR_IN)addresses[0].AddrInfo.RemoteAddr.lpSockaddr)->sin_addr;
  892. //*((LPDWORD)&((LPSOCKADDR_IN)addresses[0].AddrInfo.RemoteAddr.lpSockaddr)->sin_addr) = 0x04030201;
  893. #endif
  894. //
  895. // update the object
  896. //
  897. INET_ASSERT(m_AddressCount == 0);
  898. INET_ASSERT(m_Addresses == NULL);
  899. m_AddressCount = nAddrs;
  900. m_BadAddressCount = 0;
  901. m_Addresses = addresses;
  902. m_CurrentAddress = 0;
  903. return ERROR_SUCCESS;
  904. }