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.

624 lines
19 KiB

  1. //-----------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 1997 - 1999
  3. //
  4. // server.c
  5. //
  6. // Thread code to manage communication between RPC client and
  7. // server for the HTTP RPC proxy.
  8. //
  9. // History:
  10. //
  11. // Edward Reus 00-00-97 Initial version.
  12. //-----------------------------------------------------------------
  13. #include <sysinc.h>
  14. #include <rpc.h>
  15. #include <rpcdce.h>
  16. #include <winsock2.h>
  17. #include <httpfilt.h>
  18. #include <httpext.h>
  19. #include "ecblist.h"
  20. #include "filter.h"
  21. #include "server.h"
  22. //-----------------------------------------------------------------
  23. // Globals:
  24. //-----------------------------------------------------------------
  25. HANDLE g_hServerThread = 0;
  26. DWORD g_dwThreadId = 0;
  27. extern SERVER_INFO *g_pServerInfo;
  28. //-----------------------------------------------------------------
  29. // CleanupECB()
  30. //
  31. // When the client or server side connection is closed, they call
  32. // this function to handle cleanup of the ECB. The active ECBs are
  33. // reference counted, since its used by both the server and client
  34. // side threads. When the count goes to zero, the ECB can be
  35. // destroyed by the IIS (HSE_REQ_DONE_WITH_SESSION).
  36. //
  37. //-----------------------------------------------------------------
  38. DWORD CleanupECB( EXTENSION_CONTROL_BLOCK *pECB )
  39. {
  40. DWORD dwStatus = 0;
  41. if (DecrementECBRefCount(g_pServerInfo->pActiveECBList,pECB))
  42. {
  43. //
  44. // The ECB reference count has reached zero, we can get
  45. // rid of it:
  46. //
  47. #ifdef DBG_ECBREF
  48. DbgPrint("CleanupECB(): Destroy ECB: 0x%x\n",pECB);
  49. #endif
  50. if (!pECB->ServerSupportFunction( pECB->ConnID,
  51. HSE_REQ_DONE_WITH_SESSION,
  52. NULL, NULL, NULL))
  53. {
  54. dwStatus = GetLastError();
  55. #ifdef DBG_ERROR
  56. DbgPrint("CleanupECB(): HSE_REQ_DONE_WITH_SESSION failed: %d\n",dwStatus);
  57. #endif
  58. }
  59. }
  60. return dwStatus;
  61. }
  62. #ifdef DBG
  63. //-----------------------------------------------------------------
  64. // CheckForOldECBs()
  65. //
  66. //-----------------------------------------------------------------
  67. void CheckForOldECBs()
  68. {
  69. int i;
  70. DWORD dwStatus;
  71. DWORD dwAgeMsec;
  72. DWORD dwTickCount = GetTickCount();
  73. ACTIVE_ECB_LIST *pECBList = g_pServerInfo->pActiveECBList;
  74. ECB_ENTRY *pECBEntry;
  75. LIST_ENTRY *pEntry;
  76. LIST_ENTRY *pHead = NULL;
  77. LIST_ENTRY *pOldEntries = NULL;
  78. EXTENSION_CONTROL_BLOCK *pECB;
  79. //
  80. // Check for ECBs that are inactive (one side of connection
  81. // closed) for more that 10 minutes.
  82. //
  83. #define OLD_AGE_LIMIT 1000*60*10
  84. dwStatus = RtlEnterCriticalSection(&pECBList->cs);
  85. ASSERT(dwStatus == 0);
  86. for (i=0; i<HASH_SIZE; i++)
  87. {
  88. pHead = &(pECBList->HashTable[i]);
  89. pEntry = pHead->Flink;
  90. while (pEntry != pHead)
  91. {
  92. pECBEntry = CONTAINING_RECORD(pEntry,ECB_ENTRY,ListEntry);
  93. if (pECBEntry->dwTickCount)
  94. {
  95. // Ok, this is one where one of the server/client side
  96. // has closed the connection:
  97. //
  98. // dwAgeMsec is the age of the current ECB is msec.
  99. //
  100. if (pECBEntry->dwTickCount > dwTickCount)
  101. {
  102. // Rollover case (every ~49 days):
  103. dwAgeMsec = (0xFFFFFFFF - pECBEntry->dwTickCount) + dwTickCount;
  104. }
  105. else
  106. {
  107. dwAgeMsec = dwTickCount - pECBEntry->dwTickCount;
  108. }
  109. // ASSERT( dwAgeMsec <= OLD_AGE_LIMIT);
  110. if (dwAgeMsec > OLD_AGE_LIMIT)
  111. {
  112. RemoveEntryList(pEntry);
  113. pEntry->Blink = pOldEntries;
  114. pOldEntries = pEntry;
  115. }
  116. }
  117. pEntry = pEntry->Flink;
  118. }
  119. }
  120. dwStatus = RtlLeaveCriticalSection(&pECBList->cs);
  121. ASSERT(dwStatus == 0);
  122. while (pOldEntries)
  123. {
  124. pECBEntry = CONTAINING_RECORD(pOldEntries,ECB_ENTRY,ListEntry);
  125. pECB = pECBEntry->pECB;
  126. pOldEntries = pOldEntries->Blink;
  127. MemFree(pECBEntry);
  128. #ifdef DBG_ECBREF
  129. DbgPrint("CheckForOldECBs(): Age out pECB: 0x%x\n",pECB);
  130. #endif
  131. if (!pECB->ServerSupportFunction( pECB->ConnID,
  132. HSE_REQ_DONE_WITH_SESSION,
  133. NULL, NULL, NULL))
  134. {
  135. #ifdef DBG_ERROR
  136. DbgPrint("CheckForOldECBs(): HSE_REQ_DONE_WITH_SESSION failed: %d\n", GetLastError());
  137. #endif
  138. }
  139. }
  140. }
  141. #endif
  142. //-----------------------------------------------------------------
  143. // SendToClient()
  144. //
  145. // Forward data received from the server back to the client.
  146. //-----------------------------------------------------------------
  147. BOOL SendToClient( SERVER_INFO *pServerInfo,
  148. SERVER_OVERLAPPED *pOverlapped,
  149. DWORD dwReceiveSize,
  150. DWORD *pdwStatus )
  151. {
  152. DWORD dwSize;
  153. DWORD dwFlags = (HSE_IO_SYNC | HSE_IO_NODELAY);
  154. UCHAR *pBuffer = pOverlapped->arBuffer;
  155. EXTENSION_CONTROL_BLOCK *pECB = pOverlapped->pECB;
  156. *pdwStatus = 0;
  157. //
  158. // Forward the data to the client:
  159. //
  160. dwSize = dwReceiveSize;
  161. while (dwReceiveSize)
  162. {
  163. if (!pECB->WriteClient(pECB->ConnID,pBuffer,&dwSize,dwFlags))
  164. {
  165. *pdwStatus = GetLastError();
  166. #ifdef DBG_ERROR
  167. DbgPrint("SendToClient(): WriteClient() failed: %d\n",*pdwStatus);
  168. #endif
  169. return FALSE;
  170. }
  171. dwReceiveSize -= dwSize;
  172. if (dwReceiveSize)
  173. {
  174. pBuffer += dwSize;
  175. }
  176. }
  177. return TRUE;
  178. }
  179. //-----------------------------------------------------------------
  180. // SubmitNewRead()
  181. //
  182. // Submit a read request on the socket connected to the
  183. // RPC server process.
  184. //-----------------------------------------------------------------
  185. BOOL SubmitNewRead( SERVER_INFO *pServerInfo,
  186. SERVER_OVERLAPPED *pOverlapped,
  187. DWORD *pdwStatus )
  188. {
  189. DWORD dwBytesRead = 0;
  190. SERVER_CONNECTION *pConn = pOverlapped->pConn;
  191. *pdwStatus = 0;
  192. pOverlapped->Internal = 0;
  193. pOverlapped->InternalHigh = 0;
  194. pOverlapped->Offset = 0;
  195. pOverlapped->OffsetHigh = 0;
  196. pOverlapped->hEvent = 0;
  197. SetLastError(ERROR_SUCCESS);
  198. if (!ReadFile( (HANDLE)pConn->Socket,
  199. pOverlapped->arBuffer,
  200. READ_BUFFER_SIZE,
  201. &dwBytesRead,
  202. (OVERLAPPED*)pOverlapped ) )
  203. {
  204. *pdwStatus = GetLastError();
  205. if ( (*pdwStatus != ERROR_IO_PENDING) && (*pdwStatus != ERROR_SUCCESS) )
  206. {
  207. #ifdef DBG_ERROR
  208. DbgPrint("SubmitNewRead(): ReadFile() Socket: %d failed: %d\n",pConn->Socket,*pdwStatus);
  209. #endif
  210. return FALSE;
  211. }
  212. }
  213. return TRUE;
  214. }
  215. //-----------------------------------------------------------------
  216. // ForwardAndSubmitNewRead()
  217. //
  218. // Forward data to the client, the submit a new read on the
  219. // server.
  220. //-----------------------------------------------------------------
  221. BOOL ForwardAndSubmitNewRead( SERVER_INFO *pServerInfo,
  222. SERVER_OVERLAPPED *pOverlapped,
  223. DWORD dwReceiveSize,
  224. DWORD *pdwStatus )
  225. {
  226. DWORD dwBytesRead = 0;
  227. SERVER_CONNECTION *pConn = pOverlapped->pConn;
  228. *pdwStatus = 0;
  229. //
  230. // Forward the data to the client:
  231. //
  232. if (!SendToClient(pServerInfo,pOverlapped,dwReceiveSize,pdwStatus))
  233. {
  234. return FALSE;
  235. }
  236. //
  237. // Submit another read on the socket:
  238. //
  239. if (!SubmitNewRead(pServerInfo,pOverlapped,pdwStatus))
  240. {
  241. return FALSE;
  242. }
  243. return TRUE;
  244. }
  245. #if _MSC_FULL_VER >= 13008827
  246. #pragma warning(push)
  247. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  248. #endif
  249. //-----------------------------------------------------------------
  250. // ServerReceiveThreadProc()
  251. //
  252. // This is the receive thread for the server. It monitors the
  253. // all the sockets to RPC servers that are currently connected
  254. // to the RPC proxy. When it gets incomming data from an RPC
  255. // server socket, it forwards the data to the client, then
  256. // submits a new read on the socket that data came in on.
  257. //
  258. // Once its started, it never stops...
  259. //-----------------------------------------------------------------
  260. DWORD WINAPI ServerReceiveThreadProc( void *pvServerInfo )
  261. {
  262. int iRet;
  263. BOOL fWaitAll = FALSE;
  264. DWORD dwStatus;
  265. DWORD dwTimeout = TIMEOUT_MSEC;
  266. DWORD dwWhichEvent;
  267. ULONG_PTR dwKey;
  268. DWORD dwNumBytes;
  269. SERVER_OVERLAPPED *pOverlapped;
  270. SERVER_INFO *pServerInfo = (SERVER_INFO*)pvServerInfo;
  271. EXTENSION_CONTROL_BLOCK *pECB;
  272. DWORD dwTemp;
  273. DWORD dwSize;
  274. DWORD dwFlags;
  275. while (TRUE)
  276. {
  277. SetLastError(0);
  278. dwKey = 0;
  279. dwNumBytes = 0;
  280. pOverlapped = NULL;
  281. if (!GetQueuedCompletionStatus(pServerInfo->hIoCP,&dwNumBytes,&dwKey,(OVERLAPPED**)&pOverlapped,dwTimeout))
  282. {
  283. dwStatus = GetLastError();
  284. if (dwStatus == WAIT_TIMEOUT)
  285. {
  286. // Our reads are still posted, go around again:
  287. #ifdef DBG
  288. CheckForOldECBs();
  289. #endif
  290. continue;
  291. }
  292. else if (dwStatus == ERROR_OPERATION_ABORTED)
  293. {
  294. // The posted read on the server was aborted (why?). Try
  295. // to resubmit the read...
  296. if ( (pOverlapped)
  297. && (!SubmitNewRead(pServerInfo,pOverlapped,&dwStatus)) )
  298. {
  299. pECB = pOverlapped->pECB;
  300. CloseServerConnection(pOverlapped->pConn);
  301. FreeOverlapped(pOverlapped);
  302. CleanupECB(pECB);
  303. #ifdef DBG_ERROR
  304. DbgPrint("ServerReceiveThreadProc(): Aborted re-submit failed: %d\n",dwStatus);
  305. #endif
  306. }
  307. continue;
  308. }
  309. else if (dwStatus == ERROR_NETNAME_DELETED)
  310. {
  311. // The server connection has been closed:
  312. if (pOverlapped)
  313. {
  314. pECB = pOverlapped->pECB;
  315. CloseServerConnection(pOverlapped->pConn);
  316. FreeOverlapped(pOverlapped);
  317. CleanupECB(pECB);
  318. #ifdef DBG_ERROR
  319. DbgPrint("ServerReceiveThreadProc(): Socket(%d): ERROR_NETNAME_DELETED\n",dwKey,dwStatus);
  320. #endif
  321. }
  322. continue;
  323. }
  324. else
  325. {
  326. #ifdef DBG_ERROR
  327. DbgPrint("ServerReceiveThreadProc(): GetQueuedCompletionStatus() failed: %d\n",dwStatus);
  328. #endif
  329. if (pOverlapped)
  330. {
  331. pECB = pOverlapped->pECB;
  332. CloseServerConnection(pOverlapped->pConn);
  333. FreeOverlapped(pOverlapped);
  334. CleanupECB(pECB);
  335. }
  336. continue;
  337. }
  338. }
  339. // Check for incomming data from a server:
  340. if (pOverlapped)
  341. {
  342. pECB = pOverlapped->pECB;
  343. if (dwNumBytes)
  344. {
  345. //
  346. // data from server arrived...
  347. //
  348. if (!ForwardAndSubmitNewRead(pServerInfo,pOverlapped,dwNumBytes,&dwStatus))
  349. {
  350. CloseServerConnection(pOverlapped->pConn);
  351. FreeOverlapped(pOverlapped);
  352. CleanupECB(pECB);
  353. #ifdef DBG_ERROR
  354. DbgPrint("ServerReceiveThreadProc(): ForwardAndSubmitNewRead(): failed: %d\n",dwStatus);
  355. #endif
  356. }
  357. }
  358. else
  359. {
  360. // Receive, but zero bytes, so connection was gracefully closed...
  361. CloseServerConnection(pOverlapped->pConn);
  362. FreeOverlapped(pOverlapped);
  363. CleanupECB(pECB);
  364. }
  365. }
  366. else
  367. {
  368. // The filter called EndOfSession() and posted this message to
  369. // us to close up... dwKey is the socket in question:
  370. #ifdef DBG_ERROR
  371. DbgPrint("ServerReceiveProc(): EndOfSession(): pOverlapped == NULL\n");
  372. #endif
  373. iRet = closesocket( (SOCKET)dwKey );
  374. #ifdef DBG_COUNTS
  375. if (iRet == SOCKET_ERROR)
  376. {
  377. DbgPrint("[6] closesocket(%d) failed: %d\n",dwKey,WSAGetLastError());
  378. }
  379. else
  380. {
  381. int iCount = InterlockedDecrement(&g_iSocketCount);
  382. DbgPrint("[6] closesocket(%d): Count: %d -> %d\n",
  383. dwKey, 1+iCount, iCount );
  384. }
  385. #endif
  386. }
  387. }
  388. return 0;
  389. }
  390. #if _MSC_FULL_VER >= 13008827
  391. #pragma warning(pop)
  392. #endif
  393. //-----------------------------------------------------------------
  394. // CheckStartReceiveThread()
  395. //
  396. // Check to see of the server side receive thread is running, if
  397. // it isn't started yet, then start it.
  398. //-----------------------------------------------------------------
  399. BOOL CheckStartReceiveThread( SERVER_INFO *pServerInfo,
  400. DWORD *pdwStatus )
  401. {
  402. *pdwStatus = 0;
  403. if (!g_hServerThread)
  404. {
  405. g_hServerThread = CreateThread( NULL,
  406. 0,
  407. ServerReceiveThreadProc,
  408. (void*)pServerInfo,
  409. 0,
  410. &g_dwThreadId );
  411. if (!g_hServerThread)
  412. {
  413. *pdwStatus = GetLastError();
  414. #ifdef DBG_ERROR
  415. DbgPrint("CheckStartServerThread(): CreateThread() failed: 0x%x\n",pdwStatus);
  416. #endif
  417. return FALSE;
  418. }
  419. }
  420. return TRUE;
  421. }
  422. //-----------------------------------------------------------------
  423. // AsyncClientReadComplete()
  424. //
  425. // This function is called when data (a call) comes in from an
  426. // RPC client. It then forwards the data to the RPC server via
  427. // the function SendToServer().
  428. //-----------------------------------------------------------------
  429. void WINAPI AsyncClientReadComplete( IN EXTENSION_CONTROL_BLOCK *pECB,
  430. IN void *pvOverlapped,
  431. IN DWORD dwBytes,
  432. IN DWORD dwStatus )
  433. {
  434. int iRet;
  435. DWORD dwSize;
  436. DWORD dwFlags;
  437. DWORD dwLocalStatus;
  438. SERVER_CONNECTION *pConn;
  439. SERVER_OVERLAPPED *pOverlapped = (SERVER_OVERLAPPED*)pvOverlapped;
  440. SOCKET Socket;
  441. ASSERT(pECB == pOverlapped->pECB);
  442. pConn = pOverlapped->pConn;
  443. if (dwStatus == ERROR_SUCCESS)
  444. {
  445. if (dwBytes)
  446. {
  447. if (pOverlapped->fFirstRead)
  448. {
  449. pOverlapped->fFirstRead = FALSE;
  450. if ( (dwBytes < 72) && (pECB->lpbData) )
  451. {
  452. #ifdef DBG_ERROR
  453. DbgPrint("AsyncClientReadComplete(): Bind missing bytes: %d\n",72-dwBytes);
  454. #endif
  455. dwStatus = SendToServer(pOverlapped->pConn,pECB->lpbData,72-dwBytes);
  456. }
  457. }
  458. // Got data from the client, forward it to the server:
  459. dwStatus = SendToServer(pOverlapped->pConn,pOverlapped->arBuffer,dwBytes);
  460. // Submit a new async read on the client:
  461. if (dwStatus == ERROR_SUCCESS)
  462. {
  463. dwSize = sizeof(pOverlapped->arBuffer);
  464. dwFlags = HSE_IO_ASYNC;
  465. if (!pECB->ServerSupportFunction(pECB->ConnID,
  466. HSE_REQ_ASYNC_READ_CLIENT,
  467. pOverlapped->arBuffer,
  468. &dwSize,
  469. &dwFlags))
  470. {
  471. dwStatus = GetLastError();
  472. }
  473. }
  474. }
  475. }
  476. if ((dwBytes == 0) || (dwStatus != ERROR_SUCCESS))
  477. {
  478. //
  479. // Connection to client was closed (dwBytes == 0) or error. So
  480. // shutdown socket to server:
  481. //
  482. if (pOverlapped)
  483. {
  484. CloseServerConnection(pOverlapped->pConn);
  485. pOverlapped->pECB = NULL;
  486. FreeOverlapped(pOverlapped);
  487. CleanupECB(pECB);
  488. }
  489. #ifdef DBG_ERROR
  490. if ((dwStatus != ERROR_SUCCESS) && (dwStatus != ERROR_NETNAME_DELETED))
  491. {
  492. DbgPrint("AsyncClientReadComplete(): Erorr: %d Close server socket: %d\n",dwStatus,pConn->Socket);
  493. }
  494. #endif
  495. }
  496. }
  497. //-----------------------------------------------------------------
  498. // StartAsyncClientRead()
  499. //
  500. // Called by the RpcIsapi half of the code to start an async read
  501. // on the client connection.
  502. //-----------------------------------------------------------------
  503. BOOL StartAsyncClientRead( EXTENSION_CONTROL_BLOCK *pECB,
  504. SERVER_CONNECTION *pConn,
  505. DWORD *pdwStatus )
  506. {
  507. SERVER_OVERLAPPED *pOverlapped;
  508. pOverlapped = AllocOverlapped();
  509. if (!pOverlapped)
  510. {
  511. *pdwStatus = RPC_S_OUT_OF_MEMORY;
  512. return FALSE;
  513. }
  514. *pdwStatus = 0;
  515. pOverlapped->pECB = pECB;
  516. // The SERVER_CONNECTION (pConn) is in two separate SERVER_OVERLAPPED
  517. // structures, one for client async reads and one for server async
  518. // reads, as well as in the filter context. So it is reference counted.
  519. pOverlapped->pConn = pConn;
  520. AddRefConnection(pConn);
  521. pOverlapped->fFirstRead = TRUE;
  522. if (!pECB->ServerSupportFunction(pECB->ConnID,
  523. HSE_REQ_IO_COMPLETION,
  524. AsyncClientReadComplete,
  525. NULL,
  526. (void*)pOverlapped))
  527. {
  528. *pdwStatus = GetLastError();
  529. FreeOverlapped(pOverlapped);
  530. #ifdef DBG_ERROR
  531. DbgPrint("StartAsyncClientRead(): HSE_REQ_IO_COMPLETION Failed: %d\n",*pdwStatus);
  532. #endif
  533. return FALSE;
  534. }
  535. pOverlapped->dwBytes = sizeof(pOverlapped->arBuffer);
  536. pOverlapped->dwFlags = HSE_IO_ASYNC;
  537. if (!pECB->ServerSupportFunction(pECB->ConnID,
  538. HSE_REQ_ASYNC_READ_CLIENT,
  539. pOverlapped->arBuffer,
  540. &pOverlapped->dwBytes,
  541. &pOverlapped->dwFlags))
  542. {
  543. *pdwStatus = GetLastError();
  544. FreeOverlapped(pOverlapped);
  545. #ifdef DBG_ERROR
  546. DbgPrint("StartAsyncClientRead(): HSE_REQ_ASYNC_READ_CLIENT Failed: %d\n",*pdwStatus);
  547. #endif
  548. return FALSE;
  549. }
  550. return TRUE;
  551. }