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.

461 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. caddrlst.hxx
  5. Abstract:
  6. Contains CAddressList class definition
  7. Contents:
  8. Author:
  9. Richard L Firth (rfirth) 21-Apr-1997
  10. Revision History:
  11. 21-Apr-1997 rfirth
  12. Created
  13. --*/
  14. //
  15. // manifests
  16. //
  17. #define CSADDR_BUFFER_LENGTH (sizeof(CSADDR_INFO) + 128)
  18. //
  19. // types
  20. //
  21. //
  22. // RESOLVED_ADDRESS - a CSADDR_INFO with additional IsBad field which is set
  23. // when we fail to connect to the address
  24. //
  25. typedef struct {
  26. CSADDR_INFO AddrInfo;
  27. BOOL IsValid;
  28. } RESOLVED_ADDRESS, * LPRESOLVED_ADDRESS;
  29. //
  30. // forward references
  31. //
  32. class CFsm_ResolveHost;
  33. //
  34. // classes
  35. //
  36. class CListItem
  37. {
  38. protected:
  39. CListItem* pNext;
  40. CListItem()
  41. {
  42. pNext=NULL;
  43. }
  44. public:
  45. void SetNext(CListItem* _pNext)
  46. {
  47. pNext = _pNext;
  48. }
  49. CListItem* GetNext()
  50. {
  51. return pNext;
  52. }
  53. };
  54. //This list maintains a list of threads that have not yet exited from GHBN for the session handle.
  55. // We periodically check ( based on trimsize ), for threads that have exited and remove them from the list.
  56. class CList
  57. {
  58. protected:
  59. CCritSec _cs;
  60. ULONG _nItems;
  61. CListItem* _pHead;
  62. CListItem* _pTail;
  63. public:
  64. CList(CListItem* pHead)
  65. {
  66. _cs.Init();
  67. if (pHead)
  68. _nItems = 1;
  69. else
  70. _nItems = 0;
  71. _pHead = pHead;
  72. _pTail = pHead;
  73. }
  74. ULONG GetCount()
  75. {
  76. return _nItems;
  77. }
  78. void AddAtHead(CListItem* pItem)
  79. {
  80. if (_pHead)
  81. {
  82. pItem->SetNext(_pHead);
  83. }
  84. else
  85. {
  86. _pTail = pItem;
  87. }
  88. _pHead = pItem;
  89. ++_nItems;
  90. }
  91. void AddToTail(CListItem* pItem)
  92. {
  93. if (_pTail)
  94. {
  95. _pTail->SetNext(pItem);
  96. }
  97. else
  98. {
  99. _pHead = pItem;
  100. }
  101. _pTail = pItem;
  102. ++_nItems;
  103. }
  104. CListItem* GetHead()
  105. {
  106. return _pHead;
  107. }
  108. void SetHead(CListItem* pItem)
  109. {
  110. _pHead = pItem;
  111. }
  112. void SetTail(CListItem* pItem)
  113. {
  114. _pTail = pItem;
  115. }
  116. void ReduceCount()
  117. {
  118. --_nItems;
  119. }
  120. BOOL LockList()
  121. {
  122. if (_cs.IsInitialized())
  123. return _cs.Lock();
  124. else
  125. // try initializing again
  126. return (_cs.Init() && _cs.Lock());
  127. }
  128. void UnlockList()
  129. {
  130. _cs.Unlock();
  131. }
  132. BOOL IsInitialized()
  133. {
  134. return _cs.IsInitialized();
  135. }
  136. ~CList()
  137. {
  138. INET_ASSERT(_nItems == 0);
  139. }
  140. };
  141. class CGetHostItem;
  142. class CResolverCache
  143. {
  144. private:
  145. SERIALIZED_LIST _ResolverCache;
  146. CList* _pHandlesList;
  147. public:
  148. CResolverCache(DWORD* pdwStatus)
  149. {
  150. if (!InitializeSerializedList(&_ResolverCache))
  151. {
  152. _pHandlesList = NULL;
  153. *pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
  154. }
  155. else
  156. {
  157. _pHandlesList = New CList(NULL);
  158. if (!_pHandlesList || !_pHandlesList->IsInitialized())
  159. *pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
  160. }
  161. }
  162. ~CResolverCache();
  163. SERIALIZED_LIST* GetResolverCacheList()
  164. {
  165. return &_ResolverCache;
  166. }
  167. //Use to force all GHBN threads to terminate
  168. void ForceEmptyAndDeleteHandlesList();
  169. //Use to force graceful termination of GHBN threads
  170. void EmptyHandlesList();
  171. //Used to trim size of GHBN thread list periodically. default for trim size =1
  172. void TrimHandlesListSize(ULONG nTrimSize=1);
  173. //Used to add not-cleaned-up resources to handles list.
  174. BOOL AddToHandlesList(HANDLE hThread, CGetHostItem* pGetHostItem);
  175. };
  176. //This class exists for the following reasons:
  177. // 1. to transmit the resolver cache and hostname to the GHBN thread.
  178. // 2. to save information regarding above and the thread handle in case we time out in ResolveHost:
  179. // in which case, we need to clean up all these resources.
  180. // We don't clean up resources in the GHBN thread itself, because we may have to kill off the thread
  181. // in case we are unloaded by client without proper cleanup of session handle.
  182. class CGetHostItem: public CListItem
  183. {
  184. private:
  185. HANDLE _hThread; //GHBN thread handle to wait on
  186. LPSTR _lpszHostName; //copy of host name to free
  187. CResolverCache* _pResolverCache; //resolver cache wrapper
  188. VOID* _pAlloc; //preallocated memory to get around Rockall allocation issue.
  189. DWORD _dwAllocSize;
  190. BOOL _fDelete; //delete this memory in the destructor?
  191. public:
  192. CGetHostItem(LPSTR lpszHostName, CResolverCache* pResolverCache, VOID* pAlloc, DWORD dwAllocSize):
  193. _hThread(NULL),_lpszHostName(lpszHostName),_pResolverCache(pResolverCache),
  194. _pAlloc(pAlloc),_dwAllocSize(dwAllocSize),_fDelete(FALSE)
  195. {
  196. }
  197. VOID* GetAllocPointer()
  198. {
  199. return _pAlloc;
  200. }
  201. DWORD GetAllocSize()
  202. {
  203. return _dwAllocSize;
  204. }
  205. VOID SetDelete()
  206. {
  207. _fDelete = TRUE;
  208. }
  209. LPSTR GetHostName()
  210. {
  211. return _lpszHostName;
  212. }
  213. CResolverCache* GetResolverCache()
  214. {
  215. return _pResolverCache;
  216. }
  217. BOOL CanBeDeleted()
  218. {
  219. DWORD dwExitCode;
  220. if (GetExitCodeThread(_hThread, &dwExitCode) && (dwExitCode != STILL_ACTIVE))
  221. return TRUE;
  222. else
  223. return FALSE;
  224. }
  225. void SetThreadHandle(HANDLE hThread)
  226. {
  227. _hThread = hThread;
  228. }
  229. void ForceDelete()
  230. {
  231. DWORD dwExitCode;
  232. if (GetExitCodeThread(_hThread, &dwExitCode) && (dwExitCode != STILL_ACTIVE))
  233. return;
  234. else
  235. TerminateThread(_hThread, 0);
  236. }
  237. void WaitDelete()
  238. {
  239. WaitForSingleObject(_hThread, INFINITE);
  240. }
  241. //lpszHostname and pResolverCache will always be non-NULL ( because we check for them
  242. // before creating this in ResolveHost_Fsm )
  243. // But hThread may be NULL, in which case the destructor is called immdly.
  244. ~CGetHostItem()
  245. {
  246. FREE_FIXED_MEMORY(_lpszHostName);
  247. if (_hThread)
  248. CloseHandle(_hThread);
  249. if (_fDelete && _pAlloc)
  250. FREE_FIXED_MEMORY(_pAlloc);
  251. }
  252. };
  253. //
  254. // CAddressList - maintains list of resolved addresses for a host name/port
  255. // combination
  256. //
  257. class CAddressList {
  258. private:
  259. CCritSec m_CritSec; // grab this before updating
  260. DWORD m_ResolutionId; // determines when OK to resolve
  261. INT m_CurrentAddress; // index of current (good) address
  262. INT m_AddressCount; // number of addresses in list
  263. INT m_BadAddressCount; // number addresses already tried & failed
  264. LPRESOLVED_ADDRESS m_Addresses; // list of resolved addresses
  265. DWORD
  266. IPAddressToAddressList(
  267. IN DWORD ipAddr
  268. );
  269. DWORD
  270. HostentToAddressList(
  271. IN LPHOSTENT lpHostent
  272. );
  273. public:
  274. CAddressList() {
  275. m_CritSec.Init();
  276. m_ResolutionId = 0;
  277. m_CurrentAddress = 0;
  278. m_AddressCount = 0;
  279. m_BadAddressCount = 0;
  280. m_Addresses = NULL;
  281. }
  282. ~CAddressList() {
  283. FreeList();
  284. }
  285. BOOL Acquire(VOID) {
  286. return m_CritSec.Lock();
  287. }
  288. VOID Release(VOID) {
  289. m_CritSec.Unlock();
  290. }
  291. VOID
  292. FreeList(
  293. VOID
  294. );
  295. DWORD
  296. SetList(
  297. IN DWORD dwIpAddress
  298. );
  299. DWORD
  300. SetList(
  301. IN LPHOSTENT lpHostent
  302. );
  303. BOOL
  304. GetNextAddress(
  305. IN OUT LPDWORD lpdwResolutionId,
  306. IN OUT LPDWORD lpdwIndex,
  307. IN INTERNET_PORT nPort,
  308. OUT LPCSADDR_INFO lpResolvedAddress
  309. );
  310. VOID
  311. InvalidateAddress(
  312. IN DWORD dwResolutionId,
  313. IN DWORD dwAddressIndex
  314. );
  315. DWORD
  316. ResolveHost(
  317. IN LPSTR lpszHostName,
  318. IN OUT LPDWORD lpdwResolutionId,
  319. IN DWORD dwFlags
  320. );
  321. DWORD
  322. ResolveHost_Fsm(
  323. IN CFsm_ResolveHost * Fsm
  324. );
  325. VOID NextAddress(VOID) {
  326. ++m_CurrentAddress;
  327. if (m_CurrentAddress == m_AddressCount) {
  328. m_CurrentAddress = 0;
  329. }
  330. }
  331. LPCSADDR_INFO CurrentAddress(VOID) {
  332. return &m_Addresses[m_CurrentAddress].AddrInfo;
  333. }
  334. LPSOCKADDR LocalSockaddr() {
  335. return CurrentAddress()->LocalAddr.lpSockaddr;
  336. }
  337. INT LocalSockaddrLength() {
  338. return CurrentAddress()->LocalAddr.iSockaddrLength;
  339. }
  340. INT LocalFamily(VOID) {
  341. return (INT)LocalSockaddr()->sa_family;
  342. }
  343. INT LocalPort() {
  344. return ((LPSOCKADDR_IN)LocalSockaddr())->sin_port;
  345. }
  346. VOID SetLocalPort(INTERNET_PORT Port) {
  347. ((LPSOCKADDR_IN)LocalSockaddr())->sin_port = Port;
  348. }
  349. LPSOCKADDR RemoteSockaddr() {
  350. return CurrentAddress()->RemoteAddr.lpSockaddr;
  351. }
  352. INT RemoteSockaddrLength() {
  353. return CurrentAddress()->RemoteAddr.iSockaddrLength;
  354. }
  355. INT RemoteFamily(VOID) {
  356. return (INT)RemoteSockaddr()->sa_family;
  357. }
  358. INT RemotePort() {
  359. return ((LPSOCKADDR_IN)RemoteSockaddr())->sin_port;
  360. }
  361. INT SocketType(VOID) {
  362. return CurrentAddress()->iSocketType;
  363. }
  364. INT Protocol(VOID) {
  365. return CurrentAddress()->iProtocol;
  366. }
  367. BOOL IsCurrentAddressValid(VOID) {
  368. return m_Addresses[m_CurrentAddress].IsValid;
  369. }
  370. };