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.

831 lines
22 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. CoTrans.cxx
  5. Abstract:
  6. Common connection-oriented helper functions
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 11/11/1996 Async RPC
  11. --*/
  12. #include <precomp.hxx>
  13. #include <trans.hxx>
  14. #include <cotrans.hxx>
  15. RPC_STATUS
  16. RPC_ENTRY
  17. CO_Send(
  18. RPC_TRANSPORT_CONNECTION ThisConnection,
  19. UINT Length,
  20. BUFFER Buffer,
  21. PVOID SendContext
  22. )
  23. /*++
  24. Routine Description:
  25. Submits a send of the buffer on the connection. Will complete with
  26. ConnectionServerSend or ConnectionClientSend event either when
  27. the data has been sent on the network or when the send fails.
  28. Arguments:
  29. ThisConnection - The connection to send the data on.
  30. Length - The length of the data to send.
  31. Buffer - The data to send.
  32. SendContext - A buffer to use as the CO_SEND_CONTEXT for
  33. this operation.
  34. Return Value:
  35. RPC_S_OK
  36. RPC_P_SEND_FAILED - Connection aborted
  37. --*/
  38. {
  39. PCONNECTION pConnection = (PCONNECTION)ThisConnection;
  40. CO_SEND_CONTEXT *pSend = (CO_SEND_CONTEXT *)SendContext;
  41. BOOL b;
  42. DWORD ignored;
  43. RPC_STATUS status;
  44. pConnection->StartingWriteIO();
  45. if (pConnection->fAborted)
  46. {
  47. pConnection->WriteIOFinished();
  48. return(RPC_P_SEND_FAILED);
  49. }
  50. pSend->maxWriteBuffer = Length;
  51. pSend->pWriteBuffer = Buffer;
  52. pSend->Write.pAsyncObject = pConnection;
  53. pSend->Write.ol.hEvent = 0;
  54. pSend->Write.ol.Offset = 0;
  55. pSend->Write.ol.OffsetHigh = 0;
  56. pSend->Write.thread = I_RpcTransProtectThread();
  57. #ifdef _INTERNAL_RPC_BUILD_
  58. if (gpfnFilter)
  59. {
  60. (*gpfnFilter) (Buffer, Length, 0);
  61. }
  62. #endif
  63. status = pConnection->Send(
  64. pConnection->Conn.Handle,
  65. Buffer,
  66. Length,
  67. &ignored,
  68. &pSend->Write.ol
  69. );
  70. pConnection->WriteIOFinished();
  71. if ( (status != RPC_S_OK)
  72. && (status != ERROR_IO_PENDING) )
  73. {
  74. RpcpErrorAddRecord(EEInfoGCIO,
  75. status,
  76. EEInfoDLCOSend10,
  77. (ULONGLONG)pConnection,
  78. (ULONGLONG)Buffer,
  79. Length);
  80. VALIDATE(status)
  81. {
  82. ERROR_NETNAME_DELETED,
  83. ERROR_BROKEN_PIPE,
  84. ERROR_GRACEFUL_DISCONNECT,
  85. ERROR_NO_DATA,
  86. ERROR_NO_SYSTEM_RESOURCES,
  87. ERROR_WORKING_SET_QUOTA,
  88. ERROR_BAD_COMMAND,
  89. ERROR_OPERATION_ABORTED,
  90. ERROR_WORKING_SET_QUOTA,
  91. ERROR_PIPE_NOT_CONNECTED,
  92. WSAECONNABORTED,
  93. WSAECONNRESET,
  94. WSAENOBUFS,
  95. WSASYSCALLFAILURE
  96. } END_VALIDATE;
  97. I_RpcTransUnprotectThread(pSend->Write.thread);
  98. pConnection->Abort();
  99. return(RPC_P_SEND_FAILED);
  100. }
  101. return(RPC_S_OK);
  102. }
  103. RPC_STATUS
  104. RPC_ENTRY
  105. CO_SubmitRead(
  106. PCONNECTION pConnection
  107. )
  108. /*++
  109. Routine Description:
  110. Generic routine to submit an async read on an existing connection.
  111. Arguments:
  112. pConnection - The connection to submit the read on.
  113. pConnection->pReadBuffer - valid buffer to receive into or null.
  114. pConnection->maxReadBuffer - size of pReadBuffer or null.
  115. pConnection->iLastRead is an offset into pReadBuffer of
  116. data already read.
  117. Return Value:
  118. RPC_S_OK - Read pending
  119. RPC_P_RECEIVE_FAILED - Connection aborted
  120. --*/
  121. {
  122. BOOL b;
  123. DWORD ignored;
  124. RPC_STATUS status;
  125. if (pConnection->pReadBuffer == 0)
  126. {
  127. ASSERT(pConnection->iLastRead == 0);
  128. pConnection->pReadBuffer = TransConnectionAllocatePacket(pConnection,
  129. pConnection->iPostSize);
  130. if (pConnection->pReadBuffer == 0)
  131. {
  132. pConnection->Abort();
  133. return(RPC_P_RECEIVE_FAILED);
  134. }
  135. pConnection->maxReadBuffer = pConnection->iPostSize;
  136. }
  137. else
  138. {
  139. ASSERT(pConnection->iLastRead < pConnection->maxReadBuffer);
  140. }
  141. pConnection->StartingReadIO();
  142. if (pConnection->fAborted)
  143. {
  144. pConnection->ReadIOFinished();
  145. return(RPC_P_RECEIVE_FAILED);
  146. }
  147. pConnection->Read.thread = I_RpcTransProtectThread();
  148. pConnection->Read.ol.hEvent = 0;
  149. ASSERT(pConnection->Read.ol.Internal != STATUS_PENDING);
  150. status = pConnection->Receive(
  151. pConnection->Conn.Handle,
  152. pConnection->pReadBuffer + pConnection->iLastRead,
  153. pConnection->maxReadBuffer - pConnection->iLastRead,
  154. &ignored,
  155. &pConnection->Read.ol
  156. );
  157. pConnection->ReadIOFinished();
  158. if ( (status != RPC_S_OK)
  159. && (status != ERROR_IO_PENDING)
  160. && (status != ERROR_MORE_DATA) )
  161. {
  162. if ( status != ERROR_NETNAME_DELETED
  163. && status != ERROR_BROKEN_PIPE
  164. && status != ERROR_GRACEFUL_DISCONNECT)
  165. {
  166. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  167. DPFLTR_WARNING_LEVEL,
  168. RPCTRANS "UTIL_ReadFile failed %d on %p\n",
  169. status,
  170. pConnection));
  171. }
  172. RpcpErrorAddRecord(EEInfoGCIO,
  173. status,
  174. EEInfoDLCOSubmitRead10);
  175. // the IO system does not necessarily reset the Internal on sync failure.
  176. // Reset it because in HTTP when we encounted a sync failure on RTS receive
  177. // we may submit a second receive after a failed receive and this will
  178. // trigger the ASSERT above
  179. pConnection->Read.ol.Internal = status;
  180. I_RpcTransUnprotectThread(pConnection->Read.thread);
  181. pConnection->Abort();
  182. return(RPC_P_RECEIVE_FAILED);
  183. }
  184. // Even if the read completed here, it will also be posted to the
  185. // completion port. This means we don't need to handle the read here.
  186. return(RPC_S_OK);
  187. }
  188. RPC_STATUS
  189. RPC_ENTRY
  190. CO_Recv(
  191. RPC_TRANSPORT_CONNECTION ThisConnection
  192. )
  193. /*++
  194. Routine Description:
  195. Called be the runtime on a connection without a currently
  196. pending recv.
  197. Arguments:
  198. ThisConnection - A connection without a read pending on it.
  199. Return Value:
  200. RPC_S_OK
  201. RPC_P_RECEIVE_FAILED
  202. --*/
  203. {
  204. PCONNECTION p = (PCONNECTION)ThisConnection;
  205. if ( p->iLastRead
  206. && p->iLastRead == p->maxReadBuffer)
  207. {
  208. ASSERT(p->pReadBuffer);
  209. // This means we received a coalesced read of a complete
  210. // message. (Or that we received a coalesced read < header size)
  211. // We should complete that as it's own IO. This is very
  212. // rare.
  213. TransDbgDetail((DPFLTR_RPCPROXY_ID,
  214. DPFLTR_INFO_LEVEL,
  215. RPCTRANS "Posted coalesced data in %p of %d byte\n",
  216. p,
  217. p->iLastRead));
  218. UINT bytes;
  219. bytes = p->iLastRead;
  220. p->iLastRead = 0;
  221. p->Read.thread = I_RpcTransProtectThread();
  222. // This means we want to process this as a new receive
  223. BOOL b = PostQueuedCompletionStatus(RpcCompletionPort,
  224. bytes,
  225. TRANSPORT_POSTED_KEY,
  226. &p->Read.ol);
  227. ASSERT(b); // See complete.cxx - we can handle it here if needed.
  228. return(RPC_S_OK);
  229. }
  230. ASSERT(p->iLastRead == 0 || (p->iLastRead < p->maxReadBuffer));
  231. return(CO_SubmitRead(p));
  232. }
  233. RPC_STATUS BASE_CONNECTION::ProcessRead(IN DWORD bytes, OUT BUFFER *pBuffer,
  234. OUT PUINT pBufferLength)
  235. /*++
  236. Routine Description:
  237. Receives a message from a message or byte mode protocol.
  238. Arguments:
  239. bytes - The number of read (not including those in iLastRead).
  240. pBuffer - When returning RPC_S_OK will contain the message.
  241. pBufferLength - When return RPC_S_OK will contain the message length.
  242. Return Value:
  243. RPC_S_OK - A complete message has been returned.
  244. RPC_P_RECEIVE_FAILED - something failed.
  245. RPC_P_PARTIAL_RECEIVE - Partial message recv'd, need to submit another recv.
  246. --*/
  247. {
  248. DWORD message_size;
  249. RPC_STATUS status;
  250. bytes += iLastRead;
  251. if (bytes < sizeof(CONN_RPC_HEADER))
  252. {
  253. // Not a whole header, resubmit the read and continue.
  254. iLastRead = bytes;
  255. return(RPC_P_PARTIAL_RECEIVE);
  256. }
  257. message_size = MessageLength((PCONN_RPC_HEADER)pReadBuffer);
  258. if (message_size < sizeof(CONN_RPC_HEADER))
  259. {
  260. ASSERT(message_size >= sizeof(CONN_RPC_HEADER));
  261. Abort();
  262. return(RPC_P_RECEIVE_FAILED);
  263. }
  264. if (bytes == message_size)
  265. {
  266. // All set, have a complete request.
  267. *pBuffer = pReadBuffer;
  268. *pBufferLength = message_size;
  269. iLastRead = 0;
  270. pReadBuffer = 0;
  271. return(RPC_S_OK);
  272. }
  273. else if (message_size > bytes)
  274. {
  275. // Don't have a complete message, realloc if needed and
  276. // resubmit a read for the remaining bytes.
  277. if (maxReadBuffer < message_size)
  278. {
  279. // Buffer too small for the message.
  280. status = TransConnectionReallocPacket(this,
  281. &pReadBuffer,
  282. bytes,
  283. message_size);
  284. if (status != RPC_S_OK)
  285. {
  286. ASSERT(status == RPC_S_OUT_OF_MEMORY);
  287. Abort();
  288. return(RPC_P_RECEIVE_FAILED);
  289. }
  290. // increase the post size, but not if we are in direct
  291. // buffer mode.
  292. if (gBCacheMode == BCacheModeCached)
  293. iPostSize = message_size;
  294. }
  295. // Setup to receive exactly the remaining bytes of the message.
  296. iLastRead = bytes;
  297. maxReadBuffer = message_size;
  298. return(RPC_P_PARTIAL_RECEIVE);
  299. }
  300. // Coalesced read, save extra data. Very uncommon, impossible for
  301. // message mode protocols.
  302. ASSERT(bytes > message_size);
  303. #ifdef SPX_ON
  304. ASSERT((id == TCP) || (id == SPX) || (id == HTTP) || (id == TCP_IPv6) || (id == HTTPv2));
  305. #else
  306. ASSERT((id == TCP) || (id == HTTP) || (id == TCP_IPv6) || (id == HTTPv2));
  307. #endif
  308. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  309. DPFLTR_WARNING_LEVEL,
  310. RPCTRANS "Coalesced read of %d bytes, connection %p\n",
  311. bytes - message_size,
  312. this));
  313. // The first message and size will be returned
  314. *pBuffer = pReadBuffer;
  315. *pBufferLength = message_size;
  316. UINT extra = bytes - message_size;
  317. UINT alloc_size;
  318. // Try to find a good size of the extra PDU(s)
  319. if (extra < sizeof(CONN_RPC_HEADER))
  320. {
  321. // Not a whole header, we'll assume iPostSize;
  322. alloc_size = iPostSize;
  323. }
  324. else
  325. {
  326. #ifdef _M_IA64
  327. // The first packet may not contain a number of bytes
  328. // that align the second on an 8-byte boundary. Hence, the
  329. // structure may end up unaligned.
  330. alloc_size = MessageLengthUnaligned((PCONN_RPC_HEADER)(pReadBuffer
  331. + message_size));
  332. #else
  333. alloc_size = MessageLength((PCONN_RPC_HEADER)(pReadBuffer
  334. + message_size));
  335. #endif
  336. }
  337. if (alloc_size < extra)
  338. {
  339. // This can happen if there are more than two PDUs coalesced together
  340. // in the buffer. Or if the PDU is invalid. Or if the iPostSize is
  341. // smaller than the next PDU.
  342. alloc_size = extra;
  343. }
  344. // Allocate a new buffer to save the extra data for the next read.
  345. PBYTE pNewBuffer;
  346. pNewBuffer = TransConnectionAllocatePacket(this,
  347. alloc_size);
  348. if (0 == pNewBuffer)
  349. {
  350. // We have a complete request. We could process the request and
  351. // close the connection only after trying to send the reply.
  352. *pBuffer = 0;
  353. *pBufferLength = 0;
  354. Abort();
  355. return(RPC_P_RECEIVE_FAILED);
  356. }
  357. ASSERT(*pBuffer);
  358. // Save away extra data for the next receive
  359. RpcpMemoryCopy(pNewBuffer,
  360. pReadBuffer + *pBufferLength,
  361. extra);
  362. pReadBuffer = pNewBuffer;
  363. iLastRead = extra;
  364. maxReadBuffer = alloc_size;
  365. ASSERT(iLastRead <= maxReadBuffer);
  366. ASSERT(pReadBuffer != *pBuffer);
  367. return(RPC_S_OK);
  368. }
  369. RPC_STATUS
  370. CO_SubmitSyncRead(
  371. IN PCONNECTION pConnection,
  372. OUT BUFFER *pBuffer,
  373. OUT PUINT pMessageLength
  374. )
  375. /*++
  376. Routine Description:
  377. Called in the synchronous receive path when more data is needed
  378. in to complete the message. This function is non-blocking but
  379. it will try to read as much data as it can and may return a
  380. completed PDU.
  381. Arguments:
  382. pConnection - The connection to receive from.
  383. ->pReadBuffer
  384. ->maxReadBuffer
  385. ->iLastRead
  386. Return Value:
  387. RPC_S_OK - Ok and a complete PDU has arrived
  388. RPC_P_IO_PENDING - A receive is now outstanding on the connection.
  389. Wait for it to complete..
  390. RPC_P_RECEIVE_FAILED - Failure
  391. RPC_P_CONNECTION_SHUTDOWN - Failure - graceful close received.
  392. --*/
  393. {
  394. RPC_STATUS status;
  395. ASSERT(pConnection->pReadBuffer);
  396. if (pConnection->maxReadBuffer == pConnection->iLastRead)
  397. {
  398. // Coalesced receive and we've got one (or more) PDUs
  399. status = pConnection->ProcessRead(0, pBuffer, pMessageLength);
  400. ASSERT(status != RPC_P_PARTIAL_RECEIVE);
  401. return(status);
  402. }
  403. DWORD bytes;
  404. DWORD readbytes;
  405. ASSERT_READ_EVENT_IS_THERE(pConnection);
  406. do
  407. {
  408. BOOL b;
  409. readbytes = pConnection->maxReadBuffer - pConnection->iLastRead;
  410. pConnection->StartingReadIO();
  411. if (pConnection->fAborted)
  412. {
  413. pConnection->ReadIOFinished();
  414. return(RPC_P_RECEIVE_FAILED);
  415. }
  416. status = pConnection->Receive(pConnection->Conn.Handle,
  417. pConnection->pReadBuffer + pConnection->iLastRead,
  418. readbytes,
  419. &bytes,
  420. &pConnection->Read.ol);
  421. pConnection->ReadIOFinished();
  422. if ((status == ERROR_IO_PENDING) || (status == ERROR_IO_INCOMPLETE))
  423. {
  424. // The most common path
  425. return(RPC_P_IO_PENDING);
  426. }
  427. if (status != RPC_S_OK)
  428. {
  429. switch (status)
  430. {
  431. case ERROR_MORE_DATA:
  432. // Treat as success
  433. // Note: ReadFile doesn't return the number of bytes read in this
  434. // case even though the data is available...
  435. // It should still be right, but this double checks it.
  436. ASSERT(pConnection->Read.ol.InternalHigh == readbytes);
  437. ASSERT(MessageLength((PCONN_RPC_HEADER)pConnection->pReadBuffer) >
  438. pConnection->maxReadBuffer);
  439. bytes = readbytes;
  440. status = RPC_S_OK;
  441. break;
  442. case ERROR_GRACEFUL_DISCONNECT:
  443. RpcpErrorAddRecord(EEInfoGCIO,
  444. status,
  445. EEInfoDLCOSubmitSyncRead10);
  446. status = RPC_P_CONNECTION_SHUTDOWN;
  447. break;
  448. default:
  449. RpcpErrorAddRecord(EEInfoGCIO,
  450. status,
  451. EEInfoDLCOSubmitSyncRead20);
  452. VALIDATE(status)
  453. {
  454. STATUS_TIME_DIFFERENCE_AT_DC,
  455. ERROR_NETNAME_DELETED,
  456. ERROR_BROKEN_PIPE,
  457. ERROR_PIPE_NOT_CONNECTED,
  458. ERROR_NO_SYSTEM_RESOURCES,
  459. ERROR_COMMITMENT_LIMIT,
  460. WSAECONNRESET,
  461. WSAESHUTDOWN,
  462. WSAECONNABORTED,
  463. ERROR_UNEXP_NET_ERR,
  464. ERROR_WORKING_SET_QUOTA,
  465. ERROR_NO_DATA
  466. } END_VALIDATE;
  467. status = RPC_P_RECEIVE_FAILED;
  468. break;
  469. }
  470. }
  471. if (bytes == 0)
  472. {
  473. status = RPC_P_CONNECTION_SHUTDOWN;
  474. }
  475. if (status != RPC_S_OK)
  476. {
  477. pConnection->Abort();
  478. return(status);
  479. }
  480. // Read completed, process the data now..
  481. status = pConnection->ProcessRead(bytes, pBuffer, pMessageLength);
  482. }
  483. while (status == RPC_P_PARTIAL_RECEIVE );
  484. return(status);
  485. }
  486. RPC_STATUS
  487. RPC_ENTRY
  488. CO_SyncRecv(
  489. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  490. OUT BUFFER *pBuffer,
  491. OUT PUINT pBufferLength,
  492. IN DWORD dwTimeout
  493. )
  494. /*++
  495. Routine Description:
  496. Receive the next PDU to arrive at the connection.
  497. Arguments:
  498. ThisConnection - The connection to read from.
  499. pBuffer - If successful, points to a buffer containing the next PDU.
  500. pBufferLength - If successful, contains the length of the message.
  501. Return Value:
  502. RPC_S_OK
  503. RPC_P_RECEIVE_FAILED - Connection aborted.
  504. RPC_S_CALL_CANCELLED - Connection aborted.
  505. --*/
  506. {
  507. PCONNECTION p = (PCONNECTION)ThisConnection;
  508. DWORD bytes;
  509. RPC_STATUS status;
  510. HANDLE hEvent;
  511. ASSERT((p->type & TYPE_MASK) == CLIENT);
  512. ASSERT(p->pReadBuffer == 0);
  513. p->pReadBuffer = TransConnectionAllocatePacket(p, p->iPostSize);
  514. hEvent = I_RpcTransGetThreadEvent();
  515. if (p->pReadBuffer == 0)
  516. {
  517. p->Abort();
  518. return(RPC_P_RECEIVE_FAILED);
  519. }
  520. p->maxReadBuffer = p->iPostSize;
  521. p->iLastRead = 0;
  522. p->Read.ol.hEvent = (HANDLE)((ULONG_PTR)hEvent | 0x01);
  523. do
  524. {
  525. status = CO_SubmitSyncRead(p, pBuffer, pBufferLength);
  526. if (status != RPC_P_IO_PENDING)
  527. {
  528. ASSERT(status != RPC_S_CALL_CANCELLED);
  529. break;
  530. }
  531. status = UTIL_GetOverlappedResultEx(ThisConnection,
  532. &p->Read.ol,
  533. &bytes,
  534. TRUE, // Alertable
  535. dwTimeout);
  536. if (status != RPC_S_OK)
  537. {
  538. if (status != ERROR_MORE_DATA)
  539. {
  540. RpcpErrorAddRecord(EEInfoGCIO,
  541. status,
  542. EEInfoDLCOSyncRecv10);
  543. if ((status != RPC_S_CALL_CANCELLED) && (status != RPC_P_TIMEOUT))
  544. {
  545. status = RPC_P_RECEIVE_FAILED;
  546. }
  547. break;
  548. }
  549. // ERROR_MORE_DATA is success
  550. }
  551. status = p->ProcessRead(bytes, pBuffer, pBufferLength);
  552. }
  553. while (status == RPC_P_PARTIAL_RECEIVE);
  554. if (status == RPC_S_OK)
  555. {
  556. ASSERT(p->pReadBuffer == 0);
  557. return(RPC_S_OK);
  558. }
  559. p->Abort();
  560. if ((status == RPC_S_CALL_CANCELLED) || (status == RPC_P_TIMEOUT))
  561. {
  562. // Wait for the read to complete. Since the connection has
  563. // just been closed this won't take very long.
  564. UTIL_WaitForSyncIO(&p->Read.ol,
  565. FALSE,
  566. INFINITE);
  567. }
  568. return(status);
  569. }
  570. RPC_STATUS
  571. RPC_ENTRY
  572. CO_SyncRecv_Avrf(
  573. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  574. OUT BUFFER *pBuffer,
  575. OUT PUINT pBufferLength,
  576. IN DWORD dwTimeout
  577. )
  578. /*++
  579. Routine Description:
  580. Wrapper for CO_SyncRecv implementing corruption injection
  581. under the RPC verifier.
  582. SyncRecv member of the transport interface may only be called
  583. by the cliet, hence we inject the corruption for a client receive.
  584. Arguments:
  585. Return Value:
  586. --*/
  587. {
  588. RPC_STATUS Status;
  589. Status = CO_SyncRecv(
  590. ThisConnection,
  591. pBuffer,
  592. pBufferLength,
  593. dwTimeout);
  594. if (!Status)
  595. {
  596. if (gfRPCVerifierEnabled)
  597. {
  598. CorruptionInject(ClientReceive,
  599. pBufferLength,
  600. (void **)pBuffer);
  601. }
  602. }
  603. return Status;
  604. }
  605. void
  606. BASE_CONNECTION::Initialize (
  607. void
  608. )
  609. /*++
  610. Routine Description:
  611. Initializes a base connection. Prior initialization
  612. ensures orderly cleanup.
  613. Arguments:
  614. Return Value:
  615. --*/
  616. {
  617. type = CLIENT | CONNECTION;
  618. pReadBuffer = 0;
  619. Conn.Handle = 0;
  620. fAborted = FALSE;
  621. pReadBuffer = 0;
  622. maxReadBuffer = 0;
  623. iPostSize = gPostSize;
  624. iLastRead = 0;
  625. RpcpMemorySet(&Read.ol, 0, sizeof(Read.ol));
  626. Read.pAsyncObject = this;
  627. Read.thread = 0;
  628. InitIoCounter();
  629. }