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.

737 lines
17 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. servinfo.hxx
  5. Abstract:
  6. Contains the CServerInfo class declaration
  7. Author:
  8. Richard L Firth (rfirth) 02-Oct-1996
  9. Notes:
  10. In this implementation, we maintain a single host name per server
  11. Revision History:
  12. 02-Oct-1996 rfirth
  13. Created
  14. --*/
  15. //
  16. // manifests
  17. //
  18. #define SERVER_INFO_SIGNATURE 'fIvS'
  19. //
  20. // values for PurgeKeepAlives dwForce parameter, method & function
  21. //
  22. #define PKA_NO_FORCE 0
  23. #define PKA_NOW 1
  24. #define PKA_AUTH_FAILED 2
  25. //
  26. // data (forward references)
  27. //
  28. extern const DWORD GlobalServerInfoTimeout;
  29. //
  30. // forward references
  31. //
  32. class CFsm_GetConnection;
  33. class HTTP_REQUEST_HANDLE_OBJECT;
  34. //
  35. // classes
  36. //
  37. //
  38. // CServerInfo - we maintain an aged list of CServerInfo's. These are used as a
  39. // database of all useful information about a server
  40. //
  41. class CServerInfo {
  42. private:
  43. //
  44. // m_ServerInfoList, m_List - CServerInfo's are kept in a list
  45. //
  46. LIST_ENTRY m_List;
  47. SERIALIZED_LIST * m_ServerInfoList;
  48. //
  49. // m_Expires - system tick count at which this entry will expire
  50. //
  51. LONG m_Expires;
  52. LONG m_Wrap;
  53. //
  54. // m_ReferenceCount - number of other structures referencing this
  55. //
  56. LONG m_ReferenceCount;
  57. //
  58. // m_HostName - primary host name of the server. Stored as LOWER CASE so
  59. // that we don't have to perform case insensitive string comparisons each
  60. // time
  61. //
  62. ICSTRING m_HostName;
  63. //
  64. // m_Hash - hash value of m_HostName. Check this value first
  65. //
  66. DWORD m_Hash;
  67. //
  68. // m_ProxyLink - if this is an origin server, we link to the proxy
  69. // that may carry
  70. //
  71. CServerInfo * m_ProxyLink;
  72. //
  73. // m_dwProxyVersion - a copy of the Global Proxy Version Count,
  74. // the proxy link goes bad if version count changes
  75. //
  76. DWORD m_dwProxyVersion;
  77. //
  78. // m_HostScheme - Not used for direct connections,
  79. // only used for matching proxy info with cached information
  80. //
  81. INTERNET_SCHEME m_HostScheme;
  82. //
  83. // m_HostPort - can also be, proxy port for cached proxy server
  84. //
  85. INTERNET_PORT m_HostPort;
  86. INTERNET_HANDLE_OBJECT * m_pInternet;
  87. private:
  88. //
  89. // m_Services - bitmap of services supported by the server
  90. //
  91. union {
  92. struct {
  93. unsigned HTTP : 1; // HTTP server running at host
  94. unsigned FTP : 1; // FTP " " " "
  95. unsigned Gopher : 1; // gopher " " " "
  96. unsigned GopherPlus : 1; // gopher+ " " " "
  97. unsigned NNTP : 1; // news " " " " (future)
  98. unsigned SMTP : 1; // mail " " " " (future)
  99. unsigned CERN_Proxy : 1; // server is running CERN proxy
  100. unsigned FTP_Proxy : 1; // server is running (TIS) FTP proxy/gateway
  101. unsigned Socks_Proxy: 1; // server is a Socks Gateway
  102. } Bits;
  103. unsigned Word;
  104. } m_Services;
  105. //
  106. // m_HttpSupport - bitmap of HTTP properties supported by the server, such
  107. // as HTTP version, keep-alive, SSL/PCT, etc.
  108. //
  109. union {
  110. struct {
  111. unsigned KeepAlive : 1; // HTTP server supports keep-alive
  112. unsigned Http1_0 : 1; // " " IS HTTP/1.0
  113. unsigned Http1_1 : 1; // " " " HTTP/1.1
  114. unsigned SSL : 1; // HTTP server supports SSL
  115. unsigned PCT : 1; // HTTP server supports PCT
  116. unsigned IIS : 1; // HTTP server is MS IIS (could be running others?)
  117. unsigned BadNS : 1; // HTTP server is BAD NS Enterprise server
  118. } Bits;
  119. unsigned Word;
  120. } m_HttpSupport;
  121. //
  122. // m_Flags - collection of boolean flags
  123. //
  124. union {
  125. struct {
  126. unsigned KA_Init : 1; // KeepAliveListInitialized
  127. unsigned Unreachable: 1; // host (currently) unreachable
  128. unsigned ProxyByPassSet: 1; // has the next bit been set.
  129. unsigned ProxyByPassed: 1; // did we bypass the proxy talking to this server.
  130. unsigned ProxyScriptCached: 1; // did/are we using this entry to cache the result of JS proxy resolution
  131. } Bits;
  132. unsigned Word;
  133. } m_Flags;
  134. //
  135. // m_KeepAliveList - if the server supports keep-alive, a list of the
  136. // keep-alive connections
  137. //
  138. SERIALIZED_LIST m_KeepAliveList;
  139. //
  140. // m_Waiters - list of sync/async waiters for connections
  141. //
  142. CPriorityList m_Waiters;
  143. //
  144. // CConnectionWaiter - private class identifying waiters in m_Waiters list
  145. //
  146. class CConnectionWaiter : public CPriorityListEntry {
  147. private:
  148. DWORD m_Sync : 1;
  149. DWORD m_KeepAlive : 1;
  150. DWORD_PTR m_dwId;
  151. HANDLE m_hEvent;
  152. public:
  153. CConnectionWaiter(
  154. IN CPriorityList *pList,
  155. IN BOOL bSync,
  156. IN BOOL bKeepAlive,
  157. IN DWORD_PTR dwId,
  158. IN HANDLE hEvent,
  159. IN LONG lPriority,
  160. OUT LPDWORD lpdwStatus) : CPriorityListEntry(lPriority) {
  161. m_Sync = bSync ? 1 : 0;
  162. m_KeepAlive = bKeepAlive ? 1 : 0;
  163. m_dwId = dwId;
  164. m_hEvent = hEvent;
  165. *lpdwStatus = pList->Insert(this);
  166. }
  167. ~CConnectionWaiter() {
  168. }
  169. BOOL IsSync(VOID) {
  170. return (m_Sync == 1) ? TRUE : FALSE;
  171. }
  172. BOOL IsKeepAlive(VOID) {
  173. return (m_KeepAlive == 1) ? TRUE : FALSE;
  174. }
  175. DWORD_PTR Id(VOID) {
  176. return m_dwId;
  177. }
  178. VOID Signal(VOID) {
  179. SetEvent(m_hEvent);
  180. }
  181. };
  182. //
  183. // m_ConnectionLimit - number of simultaneous connections allowed to this
  184. // server
  185. //
  186. LONG m_ConnectionLimit;
  187. //
  188. // m_NewLimit - set when we need to change limit
  189. //
  190. LONG m_NewLimit;
  191. //
  192. // m_ConnectionsAvailable - number of connections available to this server.
  193. // If <= 0 (and not unlimited connections) then we have to wait until a
  194. // connection is freed
  195. //
  196. LONG m_ConnectionsAvailable;
  197. //
  198. // m_ActiveConnections - number of connections that are active. An active
  199. // connection is connected and sending or receiving data. This value can be
  200. // greater than m_ConnectionLimit if we are in the situation of being run
  201. // out of connections
  202. //
  203. //LONG m_ActiveConnections;
  204. //
  205. // m_LastActiveTime - timestamp (tick count) of last operation was made on
  206. // any connection to this server
  207. //
  208. DWORD m_LastActiveTime;
  209. //
  210. // m_ConnectTime - the average time to connect in milliseconds
  211. //
  212. DWORD m_ConnectTime;
  213. //
  214. // m_RTT - average Round Trip Time
  215. //
  216. DWORD m_RTT;
  217. //
  218. // m_AddressList - list of resolved addresses for this server
  219. //
  220. CAddressList m_AddressList;
  221. //
  222. // m_dwError - error code (mainly for constructor)
  223. //
  224. DWORD m_dwError;
  225. #if INET_DEBUG
  226. DWORD m_Signature;
  227. #define INIT_SERVER_INFO() m_Signature = SERVER_INFO_SIGNATURE
  228. #define CHECK_SERVER_INFO() INET_ASSERT(m_Signature == SERVER_INFO_SIGNATURE)
  229. #else
  230. #define INIT_SERVER_INFO() /* NOTHING */
  231. #define CHECK_SERVER_INFO() /* NOTHING */
  232. #endif
  233. //
  234. // private methods
  235. //
  236. ICSocket *
  237. FindKeepAliveConnection(
  238. IN DWORD dwSocketFlags,
  239. IN INTERNET_PORT nPort,
  240. IN LPSTR pszTunnelServer
  241. );
  242. BOOL
  243. KeepAliveWaiters(
  244. VOID
  245. );
  246. BOOL
  247. RunOutOfConnections(
  248. VOID
  249. );
  250. VOID
  251. UpdateConnectionLimit(
  252. VOID
  253. );
  254. public:
  255. CServerInfo(
  256. IN SERIALIZED_LIST * ServerInfoList,
  257. IN LPSTR lpszHostName,
  258. OUT DWORD* pdwError,
  259. IN DWORD dwService = INTERNET_SERVICE_HTTP,
  260. IN DWORD dwMaxConnections = WINHTTP_CONNS_PER_SERVER_UNLIMITED
  261. );
  262. ~CServerInfo();
  263. CServerInfo * Next(VOID) {
  264. return (CServerInfo *)m_List.Flink;
  265. }
  266. CServerInfo * Prev(VOID) {
  267. return (CServerInfo *)m_List.Blink;
  268. }
  269. // This code needs to handle system time roll over.
  270. // SetExpiryTime is passed the duration, and we calculate the ultimate time
  271. // However, this may result in a rollover -- e.g. if the current time is
  272. // 0xffffff00, the ultimate time could be 0x000000fd
  273. // Expired is passed the current tick count, however, and in the past
  274. // would return TRUE immediately.
  275. // Thus we set a flag is we need to wait for system time rollover to happen,
  276. VOID SetExpiryTime(DWORD dwMilliseconds = GlobalServerInfoTimeout) {
  277. DWORD dw = GetTickCountWrap();
  278. m_Expires = dw + dwMilliseconds;
  279. m_Wrap = (dw > (DWORD)m_Expires);
  280. }
  281. VOID ResetExpiryTime(VOID) {
  282. m_Expires = 0;
  283. m_Wrap = 0;
  284. }
  285. BOOL Expired(LONG dwTime = (LONG)GetTickCountWrap()) {
  286. if (m_Wrap)
  287. {
  288. m_Wrap = ((LONG)dwTime < 0);
  289. }
  290. return (!m_Wrap && (dwTime > m_Expires)) ? TRUE : FALSE;
  291. }
  292. VOID
  293. Reference(
  294. VOID
  295. );
  296. BOOL
  297. Dereference(
  298. VOID
  299. );
  300. LONG ReferenceCount(VOID) const {
  301. return m_ReferenceCount;
  302. }
  303. LPSTR GetHostName(VOID) const {
  304. return m_HostName.StringAddress();
  305. }
  306. DWORD
  307. SetCachedProxyServerInfo(
  308. IN CServerInfo * pProxyServer,
  309. IN DWORD dwProxyVersion,
  310. IN BOOL fUseProxy,
  311. IN INTERNET_SCHEME HostScheme,
  312. IN INTERNET_PORT HostPort,
  313. IN INTERNET_SCHEME ProxyScheme,
  314. IN INTERNET_PORT ProxyPort
  315. );
  316. CServerInfo *
  317. GetCachedProxyServerInfo(
  318. IN INTERNET_SCHEME HostScheme,
  319. IN INTERNET_PORT HostPort,
  320. OUT BOOL *pfCachedEntry
  321. );
  322. BOOL
  323. CopyCachedProxyInfoToProxyMsg(
  324. IN OUT AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo
  325. );
  326. BOOL Match(IN DWORD dwHash, IN LPSTR lpszHostName) {
  327. return (dwHash == m_Hash) ? m_HostName.Strcmp(lpszHostName) : FALSE;
  328. }
  329. VOID SetHTTP(VOID) {
  330. m_Services.Bits.HTTP = 1;
  331. }
  332. BOOL IsHTTP(VOID) {
  333. return m_Services.Bits.HTTP ? TRUE : FALSE;
  334. }
  335. VOID SetFTP(VOID) {
  336. m_Services.Bits.FTP = 1;
  337. }
  338. BOOL IsFTP(VOID) {
  339. return m_Services.Bits.FTP ? TRUE : FALSE;
  340. }
  341. VOID SetGopher(VOID) {
  342. m_Services.Bits.Gopher = 1;
  343. }
  344. BOOL IsGopher(VOID) {
  345. return m_Services.Bits.Gopher ? TRUE : FALSE;
  346. }
  347. VOID SetSocksGateway(VOID) {
  348. m_Services.Bits.Socks_Proxy = 1;
  349. }
  350. BOOL IsSocksGateway(VOID) {
  351. return m_Services.Bits.Socks_Proxy ? TRUE : FALSE;
  352. }
  353. VOID SetCernProxy(VOID) {
  354. m_Services.Bits.CERN_Proxy = 1;
  355. }
  356. VOID SetFTPProxy(VOID) {
  357. m_Services.Bits.FTP_Proxy = 1;
  358. }
  359. BOOL IsCernProxy(VOID) {
  360. return m_Services.Bits.CERN_Proxy ? TRUE : FALSE;
  361. }
  362. VOID SetHttp1_1(VOID) {
  363. m_HttpSupport.Bits.Http1_1 = 1;
  364. }
  365. BOOL IsHttp1_1(VOID) {
  366. return m_HttpSupport.Bits.Http1_1 ? TRUE : FALSE;
  367. }
  368. VOID SetHttp1_0(VOID) {
  369. m_HttpSupport.Bits.Http1_0 = 1;
  370. }
  371. VOID SetBadNSServer(VOID) {
  372. m_HttpSupport.Bits.BadNS = 1;
  373. }
  374. BOOL IsBadNSServer(VOID) {
  375. return m_HttpSupport.Bits.BadNS ? TRUE : FALSE;
  376. }
  377. BOOL IsHttp1_0(VOID) {
  378. return m_HttpSupport.Bits.Http1_0 ? TRUE : FALSE;
  379. }
  380. VOID SetKeepAlive(VOID) {
  381. m_HttpSupport.Bits.KeepAlive = 1;
  382. }
  383. BOOL IsKeepAlive(VOID) {
  384. return m_HttpSupport.Bits.KeepAlive ? TRUE : FALSE;
  385. }
  386. VOID SetProxyScriptCached(BOOL fSetCached) {
  387. m_Flags.Bits.ProxyScriptCached = (fSetCached) ? 1 : 0;
  388. }
  389. BOOL IsProxyScriptCached(VOID) {
  390. return m_Flags.Bits.ProxyScriptCached ? TRUE : FALSE;
  391. }
  392. VOID SetKeepAliveListInitialized(VOID) {
  393. m_Flags.Bits.KA_Init = 1;
  394. }
  395. BOOL IsKeepAliveListInitialized(VOID) {
  396. return m_Flags.Bits.KA_Init ? TRUE : FALSE;
  397. }
  398. VOID SetUnreachable(VOID) {
  399. m_Flags.Bits.Unreachable = 1;
  400. }
  401. VOID SetReachable(VOID) {
  402. m_Flags.Bits.Unreachable = 0;
  403. }
  404. BOOL IsUnreachable(VOID) {
  405. return m_Flags.Bits.Unreachable ? TRUE : FALSE;
  406. }
  407. VOID SetProxyByPassed(BOOL fProxyByPassed) {
  408. m_Flags.Bits.ProxyByPassed = fProxyByPassed ? TRUE: FALSE;
  409. m_Flags.Bits.ProxyByPassSet = TRUE;
  410. }
  411. BOOL IsProxyByPassSet(VOID)
  412. {
  413. return m_Flags.Bits.ProxyByPassSet ? TRUE : FALSE;
  414. }
  415. BOOL WasProxyByPassed(VOID) {
  416. return m_Flags.Bits.ProxyByPassed ? TRUE : FALSE;
  417. }
  418. LONG ConnectionLimit(VOID) const {
  419. return m_ConnectionLimit;
  420. }
  421. VOID SetConnectionLimit(LONG Limit) {
  422. m_ConnectionLimit = Limit;
  423. }
  424. BOOL UnlimitedConnections(VOID) {
  425. return (ConnectionLimit() == WINHTTP_CONNS_PER_SERVER_UNLIMITED) ? TRUE : FALSE;
  426. }
  427. LONG KeepAliveConnections(VOID) {
  428. return ElementsOnSerializedList(&m_KeepAliveList);
  429. }
  430. LONG AvailableConnections(VOID) const {
  431. return m_ConnectionsAvailable;
  432. }
  433. LONG TotalAvailableConnections(VOID) {
  434. return KeepAliveConnections() + AvailableConnections();
  435. }
  436. LONG GetNewLimit(VOID) const {
  437. return m_NewLimit;
  438. }
  439. VOID SetNewLimit(LONG Limit) {
  440. m_NewLimit = Limit;
  441. }
  442. BOOL IsNewLimit(VOID) {
  443. return (m_ConnectionLimit != m_NewLimit) ? TRUE : FALSE;
  444. }
  445. VOID
  446. UpdateConnectTime(
  447. IN DWORD dwConnectTime
  448. );
  449. DWORD GetConnectTime(VOID) const {
  450. return (m_ConnectTime == (DWORD)-1) ? 0 : m_ConnectTime;
  451. }
  452. VOID
  453. UpdateRTT(
  454. IN DWORD dwTime
  455. );
  456. DWORD GetRTT(VOID) const {
  457. return m_RTT;
  458. }
  459. DWORD
  460. GetConnection_Fsm(
  461. IN CFsm_GetConnection * Fsm
  462. );
  463. DWORD
  464. ReleaseConnection(
  465. IN ICSocket * lpSocket OPTIONAL
  466. );
  467. VOID
  468. RemoveWaiter(
  469. IN DWORD_PTR dwId
  470. );
  471. VOID
  472. PurgeKeepAlives(
  473. IN DWORD dwForce = PKA_NO_FORCE
  474. );
  475. BOOL
  476. GetNextAddress(
  477. IN OUT LPDWORD lpdwResolutionId,
  478. IN OUT LPDWORD lpdwIndex,
  479. IN INTERNET_PORT nPort,
  480. OUT LPCSADDR_INFO lpAddress
  481. ) {
  482. return m_AddressList.GetNextAddress(lpdwResolutionId,
  483. lpdwIndex,
  484. nPort,
  485. lpAddress
  486. );
  487. }
  488. VOID
  489. InvalidateAddress(
  490. IN DWORD dwResolutionId,
  491. IN DWORD dwAddressIndex
  492. ) {
  493. m_AddressList.InvalidateAddress(dwResolutionId, dwAddressIndex);
  494. }
  495. DWORD
  496. ResolveHost(
  497. IN OUT LPDWORD lpdwResolutionId,
  498. IN DWORD dwFlags
  499. ) {
  500. return m_AddressList.ResolveHost(GetHostName(),
  501. lpdwResolutionId,
  502. dwFlags
  503. );
  504. }
  505. DWORD GetError(VOID) const {
  506. return m_dwError;
  507. }
  508. VOID SetError(DWORD dwError = GetLastError()) {
  509. m_dwError = dwError;
  510. }
  511. //
  512. // connection activity methods
  513. //
  514. VOID SetLastActiveTime(VOID) {
  515. m_LastActiveTime = GetTickCountWrap();
  516. }
  517. VOID ResetLastActiveTime(VOID) {
  518. m_LastActiveTime = 0;
  519. }
  520. DWORD GetLastActiveTime(VOID) const {
  521. return m_LastActiveTime;
  522. }
  523. BOOL ConnectionActivity(VOID) {
  524. DWORD lastActiveTime = GetLastActiveTime();
  525. return (lastActiveTime != 0)
  526. ? (((GetTickCountWrap() - lastActiveTime)
  527. <= GlobalConnectionInactiveTimeout) ? TRUE : FALSE)
  528. : FALSE;
  529. }
  530. BOOL AllConnectionsInactive(VOID) {
  531. //return ((ActiveConnectionCount() >= ConnectionLimit())
  532. // && !ConnectionActivity())
  533. // ? TRUE
  534. // : FALSE;
  535. return !ConnectionActivity();
  536. }
  537. //
  538. // friend functions
  539. //
  540. friend
  541. CServerInfo *
  542. ContainingServerInfo(
  543. IN LPVOID lpAddress
  544. );
  545. };
  546. //
  547. // prototypes
  548. //
  549. VOID
  550. ReleaseServerInfo(
  551. IN CServerInfo * lpServerInfo
  552. );
  553. CServerInfo *
  554. ContainingServerInfo(
  555. IN LPVOID lpAddress
  556. );