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.

846 lines
19 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. #define UNLIMITED_CONNECTIONS 0xffffffff
  20. //
  21. // values for PurgeKeepAlives dwForce parameter, method & function
  22. //
  23. #define PKA_NO_FORCE 0
  24. #define PKA_NOW 1
  25. #define PKA_AUTH_FAILED 2
  26. //
  27. // data (forward references)
  28. //
  29. extern SERIALIZED_LIST GlobalServerInfoList;
  30. extern DWORD GlobalServerInfoTimeout;
  31. //
  32. // forward references
  33. //
  34. class CFsm_GetConnection;
  35. class HTTP_REQUEST_HANDLE_OBJECT;
  36. //
  37. // classes
  38. //
  39. //
  40. // CServerInfo - we maintain an aged list of CServerInfo's. These are used as a
  41. // database of all useful information about a server
  42. //
  43. class CServerInfo {
  44. private:
  45. //
  46. // m_List - CServerInfo's are kept in a list
  47. //
  48. LIST_ENTRY m_List;
  49. //
  50. // m_Expires - system tick count at which this entry will expire
  51. //
  52. LONG m_Expires;
  53. LONG m_Wrap;
  54. //
  55. // m_ReferenceCount - number of other structures referencing this
  56. //
  57. LONG m_ReferenceCount;
  58. //
  59. // m_HostName - primary host name of the server. Stored as LOWER CASE so
  60. // that we don't have to perform case insensitive string comparisons each
  61. // time
  62. //
  63. ICSTRING m_HostName;
  64. //
  65. // m_Hash - hash value of m_HostName. Check this value first
  66. //
  67. DWORD m_Hash;
  68. //
  69. // m_ProxyLink - if this is an origin server, we link to the proxy
  70. // that may carry
  71. //
  72. CServerInfo * m_ProxyLink;
  73. //
  74. // m_dwProxyVersion - a copy of the Global Proxy Version Count,
  75. // the proxy link goes bad if version count changes
  76. //
  77. DWORD m_dwProxyVersion;
  78. //
  79. // m_HostScheme - Not used for direct connections,
  80. // only used for matching proxy info with cached information
  81. //
  82. INTERNET_SCHEME m_HostScheme;
  83. //
  84. // m_HostPort - can also be, proxy port for cached proxy server
  85. //
  86. INTERNET_PORT m_HostPort;
  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_PipelinedList - list of HTTP 1.1 pipelined connections
  141. //
  142. SERIALIZED_LIST m_PipelinedList;
  143. //
  144. // m_Waiters - list of sync/async waiters for connections
  145. //
  146. CPriorityList m_Waiters;
  147. //
  148. // CConnectionWaiter - private class identifying waiters in m_Waiters list
  149. //
  150. class CConnectionWaiter : public CPriorityListEntry {
  151. private:
  152. DWORD m_Sync : 1;
  153. DWORD m_KeepAlive : 1;
  154. DWORD_PTR m_dwId;
  155. HANDLE m_hEvent;
  156. public:
  157. CConnectionWaiter(
  158. IN CPriorityList *pList,
  159. IN BOOL bSync,
  160. IN BOOL bKeepAlive,
  161. IN DWORD_PTR dwId,
  162. IN HANDLE hEvent,
  163. IN LONG lPriority) : CPriorityListEntry(lPriority) {
  164. m_Sync = bSync ? 1 : 0;
  165. m_KeepAlive = bKeepAlive ? 1 : 0;
  166. m_dwId = dwId;
  167. m_hEvent = hEvent;
  168. pList->Insert(this);
  169. }
  170. ~CConnectionWaiter() {
  171. }
  172. BOOL IsSync(VOID) {
  173. return (m_Sync == 1) ? TRUE : FALSE;
  174. }
  175. BOOL IsKeepAlive(VOID) {
  176. return (m_KeepAlive == 1) ? TRUE : FALSE;
  177. }
  178. DWORD_PTR Id(VOID) {
  179. return m_dwId;
  180. }
  181. VOID Signal(VOID) {
  182. SetEvent(m_hEvent);
  183. }
  184. };
  185. //
  186. // m_ConnectionLimit - number of simultaneous connections allowed to this
  187. // server
  188. //
  189. LONG m_ConnectionLimit;
  190. //
  191. // m_NewLimit - set when we need to change limit
  192. //
  193. LONG m_NewLimit;
  194. //
  195. // m_ConnectionsAvailable - number of connections available to this server.
  196. // If <= 0 (and not unlimited connections) then we have to wait until a
  197. // connection is freed
  198. //
  199. LONG m_ConnectionsAvailable;
  200. //
  201. // m_ActiveConnections - number of connections that are active. An active
  202. // connection is connected and sending or receiving data. This value can be
  203. // greater than m_ConnectionLimit if we are in the situation of being run
  204. // out of connections
  205. //
  206. //LONG m_ActiveConnections;
  207. //
  208. // m_LastActiveTime - timestamp (tick count) of last operation was made on
  209. // any connection to this server
  210. //
  211. DWORD m_LastActiveTime;
  212. //
  213. // m_ConnectTime - the average time to connect in milliseconds
  214. //
  215. DWORD m_ConnectTime;
  216. //
  217. // m_RTT - average Round Trip Time
  218. //
  219. DWORD m_RTT;
  220. //
  221. // m_DownloadRate - the average download rate in bytes per second
  222. //
  223. DWORD m_DownloadRate;
  224. //
  225. // m_UploadRate - the average upload rate in bytes per second. Will be
  226. // different from m_DownloadRate if using ADSL e.g.
  227. //
  228. DWORD m_UploadRate;
  229. //
  230. // m_AddressList - list of resolved addresses for this server
  231. //
  232. CAddressList m_AddressList;
  233. //
  234. // m_dwError - error code (mainly for constructor)
  235. //
  236. DWORD m_dwError;
  237. #if INET_DEBUG
  238. DWORD m_Signature;
  239. #define INIT_SERVER_INFO() m_Signature = SERVER_INFO_SIGNATURE
  240. #define CHECK_SERVER_INFO() INET_ASSERT(m_Signature == SERVER_INFO_SIGNATURE)
  241. #else
  242. #define INIT_SERVER_INFO() /* NOTHING */
  243. #define CHECK_SERVER_INFO() /* NOTHING */
  244. #endif
  245. //
  246. // private methods
  247. //
  248. ICSocket *
  249. FindKeepAliveConnection(
  250. IN DWORD dwSocketFlags,
  251. IN INTERNET_PORT nPort,
  252. IN LPSTR pszTunnelServer
  253. );
  254. BOOL
  255. KeepAliveWaiters(
  256. VOID
  257. );
  258. BOOL
  259. RunOutOfConnections(
  260. VOID
  261. );
  262. VOID
  263. UpdateConnectionLimit(
  264. VOID
  265. );
  266. public:
  267. CServerInfo(
  268. IN LPSTR lpszHostName,
  269. OUT LPDWORD pdwError,
  270. IN DWORD dwService = INTERNET_SERVICE_HTTP,
  271. IN DWORD dwMaxConnections = GlobalMaxConnectionsPerServer
  272. );
  273. ~CServerInfo();
  274. CServerInfo * Next(VOID) {
  275. return (CServerInfo *)m_List.Flink;
  276. }
  277. CServerInfo * Prev(VOID) {
  278. return (CServerInfo *)m_List.Blink;
  279. }
  280. // This code needs to handle system time roll over.
  281. // SetExpiryTime is passed the duration, and we calculate the ultimate time
  282. // However, this may result in a rollover -- e.g. if the current time is
  283. // 0xffffff00, the ultimate time could be 0x000000fd
  284. // Expired is passed the current tick count, however, and in the past
  285. // would return TRUE immediately.
  286. // Thus we set a flag is we need to wait for system time rollover to happen,
  287. VOID SetExpiryTime(DWORD dwMilliseconds = GlobalServerInfoTimeout) {
  288. DWORD dw = GetTickCountWrap();
  289. m_Expires = dw + dwMilliseconds;
  290. m_Wrap = (dw > (DWORD)m_Expires);
  291. }
  292. VOID ResetExpiryTime(VOID) {
  293. m_Expires = 0;
  294. m_Wrap = 0;
  295. }
  296. BOOL Expired(LONG dwTime = (LONG)GetTickCountWrap()) {
  297. if (m_Wrap)
  298. {
  299. m_Wrap = ((LONG)dwTime < 0);
  300. }
  301. return (!m_Wrap && (dwTime > m_Expires)) ? TRUE : FALSE;
  302. }
  303. VOID
  304. Reference(
  305. VOID
  306. );
  307. BOOL
  308. Dereference(
  309. VOID
  310. );
  311. LONG ReferenceCount(VOID) const {
  312. return m_ReferenceCount;
  313. }
  314. LPSTR GetHostName(VOID) const {
  315. return m_HostName.StringAddress();
  316. }
  317. DWORD
  318. SetCachedProxyServerInfo(
  319. IN CServerInfo * pProxyServer,
  320. IN DWORD dwProxyVersion,
  321. IN BOOL fUseProxy,
  322. IN INTERNET_SCHEME HostScheme,
  323. IN INTERNET_PORT HostPort,
  324. IN INTERNET_SCHEME ProxyScheme,
  325. IN INTERNET_PORT ProxyPort
  326. );
  327. CServerInfo *
  328. GetCachedProxyServerInfo(
  329. IN INTERNET_SCHEME HostScheme,
  330. IN INTERNET_PORT HostPort,
  331. OUT BOOL *pfCachedEntry
  332. );
  333. BOOL
  334. CopyCachedProxyInfoToProxyMsg(
  335. IN OUT AUTO_PROXY_ASYNC_MSG *pQueryForProxyInfo
  336. );
  337. BOOL Match(IN DWORD dwHash, IN LPSTR lpszHostName) {
  338. return (dwHash == m_Hash) ? m_HostName.Strcmp(lpszHostName) : FALSE;
  339. }
  340. VOID SetHTTP(VOID) {
  341. m_Services.Bits.HTTP = 1;
  342. }
  343. BOOL IsHTTP(VOID) {
  344. return m_Services.Bits.HTTP ? TRUE : FALSE;
  345. }
  346. VOID SetFTP(VOID) {
  347. m_Services.Bits.FTP = 1;
  348. }
  349. BOOL IsFTP(VOID) {
  350. return m_Services.Bits.FTP ? TRUE : FALSE;
  351. }
  352. VOID SetGopher(VOID) {
  353. m_Services.Bits.Gopher = 1;
  354. }
  355. BOOL IsGopher(VOID) {
  356. return m_Services.Bits.Gopher ? TRUE : FALSE;
  357. }
  358. VOID SetSocksGateway(VOID) {
  359. m_Services.Bits.Socks_Proxy = 1;
  360. }
  361. BOOL IsSocksGateway(VOID) {
  362. return m_Services.Bits.Socks_Proxy ? TRUE : FALSE;
  363. }
  364. VOID SetCernProxy(VOID) {
  365. m_Services.Bits.CERN_Proxy = 1;
  366. }
  367. VOID SetFTPProxy(VOID) {
  368. m_Services.Bits.FTP_Proxy = 1;
  369. }
  370. BOOL IsCernProxy(VOID) {
  371. return m_Services.Bits.CERN_Proxy ? TRUE : FALSE;
  372. }
  373. VOID SetHttp1_1(VOID) {
  374. m_HttpSupport.Bits.Http1_1 = 1;
  375. }
  376. BOOL IsHttp1_1(VOID) {
  377. return m_HttpSupport.Bits.Http1_1 ? TRUE : FALSE;
  378. }
  379. VOID SetHttp1_0(VOID) {
  380. m_HttpSupport.Bits.Http1_0 = 1;
  381. }
  382. VOID SetBadNSServer(VOID) {
  383. m_HttpSupport.Bits.BadNS = 1;
  384. }
  385. BOOL IsBadNSServer(VOID) {
  386. return m_HttpSupport.Bits.BadNS ? TRUE : FALSE;
  387. }
  388. BOOL IsHttp1_0(VOID) {
  389. return m_HttpSupport.Bits.Http1_0 ? TRUE : FALSE;
  390. }
  391. VOID SetKeepAlive(VOID) {
  392. m_HttpSupport.Bits.KeepAlive = 1;
  393. }
  394. BOOL IsKeepAlive(VOID) {
  395. return m_HttpSupport.Bits.KeepAlive ? TRUE : FALSE;
  396. }
  397. VOID SetProxyScriptCached(BOOL fSetCached) {
  398. m_Flags.Bits.ProxyScriptCached = (fSetCached) ? 1 : 0;
  399. }
  400. BOOL IsProxyScriptCached(VOID) {
  401. return m_Flags.Bits.ProxyScriptCached ? TRUE : FALSE;
  402. }
  403. VOID SetKeepAliveListInitialized(VOID) {
  404. m_Flags.Bits.KA_Init = 1;
  405. }
  406. BOOL IsKeepAliveListInitialized(VOID) {
  407. return m_Flags.Bits.KA_Init ? TRUE : FALSE;
  408. }
  409. VOID SetUnreachable(VOID) {
  410. m_Flags.Bits.Unreachable = 1;
  411. }
  412. VOID SetReachable(VOID) {
  413. m_Flags.Bits.Unreachable = 0;
  414. }
  415. BOOL IsUnreachable(VOID) {
  416. return m_Flags.Bits.Unreachable ? TRUE : FALSE;
  417. }
  418. VOID SetProxyByPassed(BOOL fProxyByPassed) {
  419. m_Flags.Bits.ProxyByPassed = fProxyByPassed ? TRUE: FALSE;
  420. m_Flags.Bits.ProxyByPassSet = TRUE;
  421. }
  422. BOOL IsProxyByPassSet(VOID)
  423. {
  424. return m_Flags.Bits.ProxyByPassSet ? TRUE : FALSE;
  425. }
  426. BOOL WasProxyByPassed(VOID) {
  427. return m_Flags.Bits.ProxyByPassed ? TRUE : FALSE;
  428. }
  429. LONG ConnectionLimit(VOID) const {
  430. return m_ConnectionLimit;
  431. }
  432. VOID SetConnectionLimit(LONG Limit) {
  433. m_ConnectionLimit = Limit;
  434. }
  435. BOOL UnlimitedConnections(VOID) {
  436. return (ConnectionLimit() == UNLIMITED_CONNECTIONS) ? TRUE : FALSE;
  437. }
  438. LONG KeepAliveConnections(VOID) {
  439. return ElementsOnSerializedList(&m_KeepAliveList);
  440. }
  441. LONG AvailableConnections(VOID) const {
  442. return m_ConnectionsAvailable;
  443. }
  444. LONG TotalAvailableConnections(VOID) {
  445. return KeepAliveConnections() + AvailableConnections();
  446. }
  447. LONG GetNewLimit(VOID) const {
  448. return m_NewLimit;
  449. }
  450. VOID SetNewLimit(LONG Limit) {
  451. m_NewLimit = Limit;
  452. }
  453. BOOL IsNewLimit(VOID) {
  454. return (m_ConnectionLimit != m_NewLimit) ? TRUE : FALSE;
  455. }
  456. VOID
  457. UpdateConnectTime(
  458. IN DWORD dwConnectTime
  459. );
  460. DWORD GetConnectTime(VOID) const {
  461. return (m_ConnectTime == (DWORD)-1) ? 0 : m_ConnectTime;
  462. }
  463. VOID
  464. UpdateRTT(
  465. IN DWORD dwTime
  466. );
  467. DWORD GetRTT(VOID) const {
  468. return m_RTT;
  469. }
  470. VOID
  471. UpdateDownloadRate(
  472. IN DWORD dwBytesPerSecond
  473. );
  474. DWORD GetDownloadRate(VOID) const {
  475. return m_DownloadRate;
  476. }
  477. VOID
  478. UpdateUploadRate(
  479. IN DWORD dwBytesPerSecond
  480. );
  481. DWORD GetUploadRate(VOID) const {
  482. return m_UploadRate;
  483. }
  484. //DWORD
  485. //GetConnection(
  486. // IN DWORD dwSocketFlags,
  487. // IN INTERNET_PORT nPort,
  488. // IN DWORD dwTimeout,
  489. // OUT ICSocket * * lplpSocket
  490. // );
  491. DWORD
  492. GetConnection_Fsm(
  493. IN CFsm_GetConnection * Fsm
  494. );
  495. DWORD
  496. ReleaseConnection(
  497. IN ICSocket * lpSocket OPTIONAL,
  498. IN BOOL fExemptConnLimit
  499. );
  500. VOID
  501. RemoveWaiter(
  502. IN DWORD_PTR dwId
  503. );
  504. VOID
  505. PurgeKeepAlives(
  506. IN DWORD dwForce = PKA_NO_FORCE
  507. );
  508. BOOL
  509. GetNextAddress(
  510. IN OUT LPDWORD lpdwResolutionId,
  511. IN OUT LPDWORD lpdwIndex,
  512. IN INTERNET_PORT nPort,
  513. OUT LPCSADDR_INFO lpAddress
  514. ) {
  515. return m_AddressList.GetNextAddress(lpdwResolutionId,
  516. lpdwIndex,
  517. nPort,
  518. lpAddress
  519. );
  520. }
  521. VOID
  522. InvalidateAddress(
  523. IN DWORD dwResolutionId,
  524. IN DWORD dwAddressIndex
  525. ) {
  526. m_AddressList.InvalidateAddress(dwResolutionId, dwAddressIndex);
  527. }
  528. DWORD
  529. ResolveHost(
  530. IN OUT LPDWORD lpdwResolutionId,
  531. IN DWORD dwFlags
  532. ) {
  533. return m_AddressList.ResolveHost(GetHostName(),
  534. lpdwResolutionId,
  535. dwFlags
  536. );
  537. }
  538. DWORD GetError(VOID) const {
  539. return m_dwError;
  540. }
  541. VOID SetError(DWORD dwError = GetLastError()) {
  542. m_dwError = dwError;
  543. }
  544. //
  545. // connection activity methods
  546. //
  547. //VOID AddActiveConnection(VOID) {
  548. // LockSerializedList(&m_Waiters);
  549. //
  550. // INET_ASSERT(m_ActiveConnections >= 0);
  551. //
  552. // ++m_ActiveConnections;
  553. // UnlockSerializedList(&m_Waiters);
  554. //}
  555. //
  556. //VOID RemoveActiveConnection(VOID) {
  557. // LockSerializedList(&m_Waiters);
  558. // --m_ActiveConnections;
  559. //
  560. // INET_ASSERT(m_ActiveConnections >= 0);
  561. //
  562. // UnlockSerializedList(&m_Waiters);
  563. //}
  564. //
  565. //LONG ActiveConnectionCount(VOID) const {
  566. //
  567. // INET_ASSERT(m_ActiveConnections >= 0);
  568. //
  569. // return m_ActiveConnections;
  570. //}
  571. VOID SetLastActiveTime(VOID) {
  572. m_LastActiveTime = GetTickCountWrap();
  573. }
  574. VOID ResetLastActiveTime(VOID) {
  575. m_LastActiveTime = 0;
  576. }
  577. DWORD GetLastActiveTime(VOID) const {
  578. return m_LastActiveTime;
  579. }
  580. BOOL ConnectionActivity(VOID) {
  581. DWORD lastActiveTime = GetLastActiveTime();
  582. return (lastActiveTime != 0)
  583. ? (((GetTickCountWrap() - lastActiveTime)
  584. <= GlobalConnectionInactiveTimeout) ? TRUE : FALSE)
  585. : FALSE;
  586. }
  587. BOOL AllConnectionsInactive(VOID) {
  588. //return ((ActiveConnectionCount() >= ConnectionLimit())
  589. // && !ConnectionActivity())
  590. // ? TRUE
  591. // : FALSE;
  592. return !ConnectionActivity();
  593. }
  594. //
  595. // friend functions
  596. //
  597. friend
  598. CServerInfo *
  599. ContainingServerInfo(
  600. IN LPVOID lpAddress
  601. );
  602. };
  603. //
  604. // prototypes
  605. //
  606. DWORD
  607. GetServerInfo(
  608. IN LPSTR lpszHostName,
  609. IN DWORD dwServiceType,
  610. IN BOOL bDoResolution,
  611. OUT CServerInfo * * lplpServerInfo
  612. );
  613. CServerInfo *
  614. FindServerInfo(
  615. IN LPSTR lpszHostName
  616. );
  617. CServerInfo *
  618. FindNearestServer(
  619. VOID
  620. );
  621. VOID
  622. ReleaseServerInfo(
  623. IN CServerInfo * lpServerInfo
  624. );
  625. VOID
  626. PurgeServerInfoList(
  627. IN BOOL bForce
  628. );
  629. VOID
  630. PurgeKeepAlives(
  631. IN DWORD dwForce = PKA_NO_FORCE
  632. );
  633. DWORD
  634. PingServerInfoList(
  635. OUT LPBOOL lpbUnreachable
  636. );
  637. DWORD
  638. LoadServerInfoDatabase(
  639. VOID
  640. );
  641. DWORD
  642. SaveServerInfoDatabase(
  643. VOID
  644. );
  645. CServerInfo *
  646. ContainingServerInfo(
  647. IN LPVOID lpAddress
  648. );