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.

1858 lines
49 KiB

  1. /*++
  2. Copyright (c) 1994-1997 Microsoft Corporation
  3. Module Name:
  4. read.cxx
  5. Abstract:
  6. This file contains the implementation of the HttpReadData API.
  7. Contents:
  8. HttpReadData
  9. CFsm_HttpReadData::RunSM
  10. HTTP_REQUEST_HANDLE_OBJECT::HttpReadData_Fsm
  11. HTTP_REQUEST_HANDLE_OBJECT::ReadData
  12. CFsm_ReadData::RunSM
  13. HTTP_REQUEST_HANDLE_OBJECT::ReadData_Fsm
  14. HTTP_REQUEST_HANDLE_OBJECT::QueryDataAvailable
  15. CFsm_HttpQueryAvailable::RunSM
  16. HTTP_REQUEST_HANDLE_OBJECT::QueryAvailable_Fsm
  17. HTTP_REQUEST_HANDLE_OBJECT::DrainResponse
  18. CFsm_DrainResponse::RunSM
  19. HTTP_REQUEST_HANDLE_OBJECT::DrainResponse_Fsm
  20. Author:
  21. Keith Moore (keithmo) 16-Nov-1994
  22. Revision History:
  23. Modified to make HttpReadData remotable. madana (2/8/95)
  24. --*/
  25. #include <wininetp.h>
  26. #include <perfdiag.hxx>
  27. #include "httpp.h"
  28. //
  29. // private prototypes
  30. //
  31. PRIVATE
  32. VOID
  33. FilterHeaders(
  34. IN LPSTR lpszHeaderInfo,
  35. OUT LPDWORD lpdwLen
  36. );
  37. //
  38. // functions
  39. //
  40. DWORD
  41. HttpReadData(
  42. IN HINTERNET hRequest,
  43. OUT LPVOID lpBuffer,
  44. IN DWORD dwNumberOfBytesToRead,
  45. OUT LPDWORD lpdwNumberOfBytesRead,
  46. IN DWORD dwSocketFlags
  47. )
  48. /*++
  49. Routine Description:
  50. Reads a block of data from an outstanding HTTP request
  51. Assumes: 1. this function can only be called from InternetReadFile() which
  52. globally validates parameters for all Internet data read
  53. functions
  54. 2. We will never get a request for 0 bytes at this level. This
  55. request will have been handled in InternetReadFile()
  56. Arguments:
  57. hRequest - mapped HTTP request handle
  58. lpBuffer - pointer to the buffer to receive the data
  59. dwNumberOfBytesToRead - number of bytes to read into lpBuffer
  60. lpdwNumberOfBytesRead - number of bytes read into lpBuffer
  61. dwSocketFlags - controlling socket operation
  62. Return Value:
  63. TRUE - The data was read successfully. lpdwNumberOfBytesRead points to the
  64. number of BYTEs actually read. This value will be set to zero
  65. when the transfer has completed.
  66. FALSE - The operation failed. Error status is available by calling
  67. GetLastError().
  68. --*/
  69. {
  70. DEBUG_ENTER((DBG_HTTP,
  71. Dword,
  72. "HttpReadData",
  73. "%#x, %#x, %d, %#x, %#x",
  74. hRequest,
  75. lpBuffer,
  76. dwNumberOfBytesToRead,
  77. lpdwNumberOfBytesRead,
  78. dwSocketFlags
  79. ));
  80. DWORD error;
  81. HTTP_REQUEST_HANDLE_OBJECT* pRequest =
  82. (HTTP_REQUEST_HANDLE_OBJECT*) hRequest;
  83. error = DoFsm(New CFsm_HttpReadData(lpBuffer,
  84. dwNumberOfBytesToRead,
  85. lpdwNumberOfBytesRead,
  86. dwSocketFlags,
  87. pRequest
  88. ));
  89. DEBUG_LEAVE(error);
  90. return error;
  91. }
  92. DWORD
  93. CFsm_HttpReadData::RunSM(
  94. IN CFsm * Fsm
  95. )
  96. /*++
  97. Routine Description:
  98. description-of-function.
  99. Arguments:
  100. Fsm -
  101. Return Value:
  102. DWORD
  103. --*/
  104. {
  105. DEBUG_ENTER((DBG_HTTP,
  106. Dword,
  107. "CFsm_HttpReadData::RunSM",
  108. "%#x",
  109. Fsm
  110. ));
  111. DWORD error;
  112. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  113. CFsm_HttpReadData * stateMachine = (CFsm_HttpReadData *)Fsm;
  114. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
  115. switch (Fsm->GetState()) {
  116. case FSM_STATE_INIT:
  117. case FSM_STATE_CONTINUE:
  118. error = pRequest->HttpReadData_Fsm(stateMachine);
  119. break;
  120. default:
  121. error = ERROR_WINHTTP_INTERNAL_ERROR;
  122. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  123. INET_ASSERT(FALSE);
  124. break;
  125. }
  126. DEBUG_LEAVE(error);
  127. return error;
  128. }
  129. DWORD
  130. HTTP_REQUEST_HANDLE_OBJECT::HttpReadData_Fsm(
  131. IN CFsm_HttpReadData * Fsm
  132. )
  133. /*++
  134. Routine Description:
  135. description-of-function.
  136. Arguments:
  137. Fsm -
  138. Return Value:
  139. DWORD
  140. --*/
  141. {
  142. DEBUG_ENTER((DBG_HTTP,
  143. Dword,
  144. "HTTP_REQUEST_HANDLE_OBJECT::HttpReadData_Fsm",
  145. "%#x",
  146. Fsm
  147. ));
  148. CFsm_HttpReadData & fsm = *Fsm;
  149. DWORD error = fsm.GetError();
  150. if (fsm.GetState() == FSM_STATE_INIT) {
  151. if (!CheckReceiveResponseState() || !IsValidHttpState(READ)) {
  152. error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
  153. goto quit;
  154. }
  155. error = ReadData(fsm.m_lpBuffer,
  156. fsm.m_dwNumberOfBytesToRead,
  157. fsm.m_lpdwNumberOfBytesRead,
  158. FALSE, // BUGBUG RFirthRemove on chkin
  159. fsm.m_dwSocketFlags
  160. );
  161. if (error != ERROR_SUCCESS) {
  162. goto quit;
  163. }
  164. }
  165. quit:
  166. if (error != ERROR_IO_PENDING) {
  167. fsm.SetDone();
  168. }
  169. PERF_LOG(PE_TRACE, 0x1002);
  170. DEBUG_LEAVE(error);
  171. return error;
  172. }
  173. //
  174. // HTTP_REQUEST_HANDLE_OBJECT methods
  175. //
  176. DWORD
  177. HTTP_REQUEST_HANDLE_OBJECT::ReadData(
  178. OUT LPVOID lpBuffer,
  179. IN DWORD dwNumberOfBytesToRead,
  180. OUT LPDWORD lpdwNumberOfBytesRead,
  181. IN BOOL fNoAsync, // BUGBUG RFirthRemove on DrainSocket checkin
  182. IN DWORD dwSocketFlags
  183. )
  184. /*++
  185. Routine Description:
  186. HTTP_REQUEST_HANDLE_OBJECT ReadData method
  187. Reads data into users buffer. Reads from header buffer if data exists
  188. there, or reads from the socket
  189. Arguments:
  190. lpBuffer - pointer to users buffer
  191. dwNumberOfBytesToRead - size of buffer/number of bytes to read
  192. lpdwNumberOfBytesRead - pointer to returned number of bytes read
  193. fNoAsync - TRUE if we want to override defaults and have
  194. no Async Read.
  195. dwSocketFlags - controlling socket operation
  196. Return Value:
  197. DWORD
  198. Success - ERROR_SUCCESS
  199. Failure - WSA error
  200. --*/
  201. {
  202. DEBUG_ENTER((DBG_HTTP,
  203. Dword,
  204. "HTTP_REQUEST_HANDLE_OBJECT::ReadData",
  205. "%#x, %d, %#x, %B, %#x",
  206. lpBuffer,
  207. dwNumberOfBytesToRead,
  208. lpdwNumberOfBytesRead,
  209. fNoAsync,
  210. dwSocketFlags
  211. ));
  212. DWORD error = DoFsm(New CFsm_ReadData(lpBuffer,
  213. dwNumberOfBytesToRead,
  214. lpdwNumberOfBytesRead,
  215. fNoAsync,
  216. dwSocketFlags,
  217. this
  218. ));
  219. DEBUG_LEAVE(error);
  220. return error;
  221. }
  222. DWORD
  223. CFsm_ReadData::RunSM(
  224. IN CFsm * Fsm
  225. )
  226. /*++
  227. Routine Description:
  228. description-of-function.
  229. Arguments:
  230. Fsm -
  231. Return Value:
  232. DWORD
  233. --*/
  234. {
  235. DEBUG_ENTER((DBG_HTTP,
  236. Dword,
  237. "CFsm_ReadData::RunSM",
  238. "%#x",
  239. Fsm
  240. ));
  241. DWORD error;
  242. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  243. CFsm_ReadData * stateMachine = (CFsm_ReadData *)Fsm;
  244. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
  245. switch (Fsm->GetState()) {
  246. case FSM_STATE_INIT:
  247. case FSM_STATE_CONTINUE:
  248. error = pRequest->ReadData_Fsm(stateMachine);
  249. break;
  250. default:
  251. error = ERROR_WINHTTP_INTERNAL_ERROR;
  252. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  253. INET_ASSERT(FALSE);
  254. break;
  255. }
  256. DEBUG_LEAVE(error);
  257. return error;
  258. }
  259. DWORD
  260. HTTP_REQUEST_HANDLE_OBJECT::ReadData_Fsm(
  261. IN CFsm_ReadData * Fsm
  262. )
  263. /*++
  264. Routine Description:
  265. description-of-function.
  266. Arguments:
  267. Fsm -
  268. Return Value:
  269. DWORD
  270. --*/
  271. {
  272. DEBUG_ENTER((DBG_HTTP,
  273. Dword,
  274. "HTTP_REQUEST_HANDLE_OBJECT::ReadData_Fsm",
  275. "%#x",
  276. Fsm
  277. ));
  278. PERF_LOG(PE_TRACE, 0x6001);
  279. CFsm_ReadData & fsm = *Fsm;
  280. DWORD error = ERROR_SUCCESS;
  281. if (fsm.GetState() == FSM_STATE_CONTINUE) {
  282. PERF_LOG(PE_TRACE, 0x6101);
  283. error = fsm.GetError();
  284. goto receive_continue;
  285. }
  286. fsm.m_dwBytesRead = 0;
  287. fsm.m_dwBufferLeft = fsm.m_dwNumberOfBytesToRead;
  288. fsm.m_nBytesCopied = 0;
  289. //
  290. // if there's no data then we're done
  291. //
  292. if (!IsData()) {
  293. DEBUG_PRINT(HTTP,
  294. ERROR,
  295. ("!IsData()\n"
  296. ));
  297. SetState(HttpRequestStateReopen);
  298. INET_ASSERT(error == ERROR_SUCCESS);
  299. goto quit;
  300. }
  301. //
  302. // If using keep-alive, reduce output buffer so we don't over-read.
  303. //
  304. if (IsKeepAlive() && IsContentLength()) {
  305. if (_BytesRemaining == 0) {
  306. INET_ASSERT(error == ERROR_SUCCESS);
  307. PERF_LOG(PE_TRACE, 0x6102);
  308. goto done;
  309. }
  310. PERF_LOG(PE_TRACE, 0x6103);
  311. fsm.m_dwBufferLeft = min(fsm.m_dwBufferLeft, _BytesRemaining);
  312. }
  313. //
  314. // if there's data left in the response buffer then copy it
  315. //
  316. fsm.m_bEof = FALSE;
  317. if (IsBufferedData()) {
  318. DWORD amountToCopy = min(fsm.m_dwNumberOfBytesToRead, BufferDataAvailToRead());
  319. if (amountToCopy != 0) {
  320. PERF_LOG(PE_TRACE, 0x6104);
  321. DEBUG_PRINT(HTTP,
  322. INFO,
  323. ("Copying %d (%#x) bytes from header buffer @ %#x - %d left\n",
  324. amountToCopy,
  325. amountToCopy,
  326. BufferedDataStart(),
  327. BufferDataAvailToRead() - amountToCopy
  328. ));
  329. memcpy(fsm.m_lpBuffer, BufferedDataStart(), amountToCopy);
  330. ReduceDataAvailToRead(amountToCopy);
  331. fsm.m_dwBytesRead += amountToCopy;
  332. fsm.m_dwBufferLeft -= amountToCopy;
  333. fsm.m_nBytesCopied += amountToCopy;
  334. //
  335. // we don't update lpBuffer here. Receive() takes the address of
  336. // the start of the buffer
  337. //
  338. }
  339. //
  340. // if we exhausted all the buffer space, then we're done
  341. //
  342. if (fsm.m_dwBufferLeft == 0) {
  343. PERF_LOG(PE_TRACE, 0x6105);
  344. goto done;
  345. }
  346. }
  347. //
  348. // find out if we're async. Even though the handle was created for async I/O
  349. // the request may be satisfied immediately
  350. //
  351. DWORD asyncFlags;
  352. if ( fsm.m_fNoAsync ) // BUGBUG RFirthRemove on Checkin of DrainSocket
  353. asyncFlags = 0;
  354. else
  355. asyncFlags = (IsAsyncHandle()
  356. && (fsm.m_dwBufferLeft > AvailableDataLength()))
  357. ? SF_NON_BLOCKING
  358. : 0
  359. ;
  360. //
  361. // if we have data already received in the query buffer, then return that
  362. //
  363. if (HaveQueryData()) {
  364. PERF_LOG(PE_TRACE, 0x6106);
  365. DWORD nCopied;
  366. nCopied = CopyQueriedData((LPVOID)((LPBYTE)fsm.m_lpBuffer + fsm.m_dwBytesRead),
  367. fsm.m_dwBufferLeft
  368. );
  369. DEBUG_PRINT(HTTP,
  370. INFO,
  371. ("Copied %d (%#x) bytes from query buffer @ %#x - %d left\n",
  372. nCopied,
  373. nCopied,
  374. (LPBYTE)_QueryBuffer - _QueryOffset,
  375. _QueryBytesAvailable
  376. ));
  377. fsm.m_dwBytesRead += nCopied;
  378. fsm.m_dwBufferLeft -= nCopied;
  379. fsm.m_nBytesCopied += nCopied;
  380. if (fsm.m_dwBufferLeft == 0) {
  381. goto done;
  382. }
  383. }
  384. if (HaveReadFileExData()) {
  385. PERF_LOG(PE_TRACE, 0x6107);
  386. *(LPBYTE)fsm.m_lpBuffer = GetReadFileExData();
  387. --fsm.m_dwNumberOfBytesToRead;
  388. --fsm.m_dwBufferLeft;
  389. ++fsm.m_dwBytesRead;
  390. DEBUG_PRINT(HTTP,
  391. INFO,
  392. ("Copied 1 byte (%#x) from ReadFileEx buffer %#x\n",
  393. (BYTE)_ReadFileExData & 0xff,
  394. &_ReadFileExData
  395. ));
  396. if (fsm.m_dwBufferLeft == 0) {
  397. goto done;
  398. }
  399. }
  400. //
  401. // If the Chunk parser claims we're done, then we're done,
  402. // stop ready and tell the reader
  403. //
  404. if ( IsChunkEncoding() && IsDecodingFinished() )
  405. {
  406. PERF_LOG(PE_TRACE, 0x6108);
  407. fsm.m_bEof = TRUE;
  408. goto done;
  409. }
  410. //
  411. // we're about to check the socket. Make sure its valid to do so
  412. //
  413. //INET_ASSERT(_Socket != NULL);
  414. if ((_Socket == NULL) || !_Socket->IsOpen()) {
  415. //
  416. // socket was closed - no more data
  417. //
  418. //
  419. // there is no more data to be received on this object
  420. //
  421. SetData(FALSE);
  422. //
  423. // this object can now be re-used
  424. //
  425. SetState(HttpRequestStateReopen);
  426. fsm.m_bEof = TRUE;
  427. PERF_LOG(PE_TRACE, 0x6109);
  428. goto quit;
  429. }
  430. read_again:
  431. fsm.m_nBytes = fsm.m_dwBytesRead;
  432. //
  433. // if we had a content-length and we don't think there is any data left to
  434. // read then we're done
  435. //
  436. if (IsContentLength() && (_BytesInSocket == 0)) {
  437. fsm.m_bEof = TRUE;
  438. PERF_LOG(PE_TRACE, 0x6110);
  439. goto done;
  440. }
  441. //
  442. // receive data into user's buffer. Because we don't own the buffer, we
  443. // cannot resize it
  444. //
  445. LPVOID lpBuffer;
  446. DWORD dwBytesToRead;
  447. DWORD dwBufferLeft;
  448. DWORD dwBytesRead;
  449. lpBuffer = fsm.m_lpBuffer;
  450. dwBytesToRead = fsm.m_dwNumberOfBytesToRead;
  451. dwBufferLeft = fsm.m_dwBufferLeft;
  452. dwBytesRead = fsm.m_dwBytesRead;
  453. //INET_ASSERT(!(fsm.m_dwSocketFlags & SF_NO_WAIT)
  454. // ? (fsm.m_dwBufferLeft <= _BytesRemaining)
  455. // : TRUE);
  456. PERF_LOG(PE_TRACE, 0x6111);
  457. if (IsBadNSServer() && !IsConnCloseResponse()) {
  458. SetBadNSReceiveTimeout();
  459. }
  460. error = _Socket->Receive(&fsm.m_lpBuffer,
  461. &fsm.m_dwNumberOfBytesToRead,
  462. &fsm.m_dwBufferLeft,
  463. &fsm.m_dwBytesRead,
  464. 0,
  465. SF_INDICATE
  466. | ((fsm.m_dwSocketFlags & SF_NO_WAIT)
  467. ? SF_NO_WAIT
  468. : (IsChunkEncoding() ? 0 : SF_RECEIVE_ALL)),
  469. &fsm.m_bEof
  470. );
  471. //
  472. // only if we performed an asynchronous no-wait receive and there was no
  473. // data available in the socket will we get WSAEWOULDBLOCK. Make another
  474. // receive request, this time without no-wait. It will complete
  475. // asynchronously and the app must make another no-wait request
  476. //
  477. if (error == WSAEWOULDBLOCK) {
  478. PERF_LOG(PE_TRACE, 0x6112);
  479. INET_ASSERT(fsm.m_dwSocketFlags & SF_NO_WAIT);
  480. INET_ASSERT(!fsm.m_bEof);
  481. //
  482. // BUGBUG - IsAsyncHandle() || IsAsyncRequest()
  483. //
  484. if ((fsm.m_dwBytesRead == 0) && IsAsyncHandle()) {
  485. DEBUG_PRINT(HTTP,
  486. INFO,
  487. ("Initiating wait-for-data (1-byte read)\n"
  488. ));
  489. fsm.m_lpBuffer = (LPVOID)&_ReadFileExData;
  490. fsm.m_dwNumberOfBytesToRead = 1;
  491. fsm.m_dwBufferLeft = 1;
  492. fsm.m_dwSocketFlags &= ~SF_NO_WAIT;
  493. INET_ASSERT(!_HaveReadFileExData);
  494. SetReadFileExData();
  495. _ReadFileExData = 0;
  496. //INET_ASSERT(fsm.m_dwBufferLeft <= _BytesRemaining);
  497. PERF_LOG(PE_TRACE, 0x6113);
  498. if (IsBadNSServer() && !IsConnCloseResponse()) {
  499. SetBadNSReceiveTimeout();
  500. }
  501. error = _Socket->Receive(&fsm.m_lpBuffer,
  502. &fsm.m_dwNumberOfBytesToRead,
  503. &fsm.m_dwBufferLeft,
  504. &fsm.m_dwBytesRead,
  505. 0,
  506. fsm.m_dwSocketFlags,
  507. &fsm.m_bEof
  508. );
  509. if (error == ERROR_SUCCESS) {
  510. PERF_LOG(PE_TRACE, 0x6114);
  511. BOOL fReadNothing = (fsm.m_dwBytesRead == 0 ? TRUE : FALSE);
  512. //
  513. // we have successfully read a single byte from the socket.
  514. //
  515. //INET_ASSERT(FALSE);
  516. fsm.m_lpBuffer = lpBuffer;
  517. fsm.m_dwNumberOfBytesToRead = dwBytesToRead;
  518. fsm.m_dwBufferLeft = dwBufferLeft;
  519. fsm.m_dwBytesRead = dwBytesRead;
  520. if (fReadNothing) {
  521. // Don't copy if nothing was actually read.
  522. ResetReadFileExData();
  523. }
  524. else {
  525. *(LPBYTE)fsm.m_lpBuffer = GetReadFileExData();
  526. --fsm.m_dwBufferLeft;
  527. ++fsm.m_dwBytesRead;
  528. }
  529. //
  530. // BUGBUG - if socket unblocked already, should go round & read
  531. // again, not just return 1 byte
  532. //
  533. }
  534. PERF_LOG(PE_TRACE, 0x6115);
  535. } else {
  536. PERF_LOG(PE_TRACE, 0x6116);
  537. DEBUG_PRINT(HTTP,
  538. WARNING,
  539. ("Not initiating wait-for-data: bytesRead = %d, asyncHandle = %B\n",
  540. fsm.m_dwBytesRead,
  541. IsAsyncHandle()
  542. ));
  543. //
  544. // read data from buffers but nothing available from socket
  545. //
  546. error = ERROR_SUCCESS;
  547. }
  548. }
  549. if (error == ERROR_IO_PENDING) {
  550. PERF_LOG(PE_TRACE, 0x6117);
  551. goto quit_pending;
  552. }
  553. receive_continue:
  554. PERF_LOG(PE_TRACE, 0x6118);
  555. //
  556. // if we timed-out while talking to 'bad' NS server (returns HTTP/1.1 but
  557. // content-length or chunked encoding info) then close the connection and
  558. // reset any RFX status. We return SUCCESS in this case
  559. //
  560. if ((error == ERROR_WINHTTP_TIMEOUT) && IsBadNSServer()) {
  561. DEBUG_PRINT(HTTP,
  562. INFO,
  563. ("Bad NS server: Closing connection %#x/%d on timeout\n",
  564. _Socket ? _Socket->GetSocket() : -1,
  565. _Socket ? _Socket->GetSourcePort() : -1
  566. ));
  567. CloseConnection(TRUE);
  568. ResetReadFileExData();
  569. SetData(FALSE);
  570. fsm.m_bEof = TRUE;
  571. error = ERROR_SUCCESS;
  572. goto quit;
  573. }
  574. if (error == ERROR_SUCCESS) {
  575. if (IsContentLength()) {
  576. INET_ASSERT(fsm.m_dwBytesRead >= fsm.m_nBytes);
  577. _BytesInSocket -= fsm.m_dwBytesRead - fsm.m_nBytes;
  578. INET_ASSERT((int)_BytesInSocket >= 0);
  579. if ((int)_BytesInSocket < 0) {
  580. _BytesInSocket = 0;
  581. }
  582. }
  583. if ( IsChunkEncoding() && !(HaveReadFileExData()))
  584. {
  585. PERF_LOG(PE_TRACE, 0x6119);
  586. DWORD dwChunkBytesRead = 0;
  587. DWORD dwChunkBytesWritten = 0;
  588. error = _ResponseFilterList.Decode(
  589. (LPBYTE)fsm.m_lpBuffer + fsm.m_nBytesCopied,
  590. fsm.m_dwBytesRead - fsm.m_nBytesCopied,
  591. NULL,
  592. NULL,
  593. &dwChunkBytesRead,
  594. &dwChunkBytesWritten);
  595. // When no error, the number of bytes read should match the input byte count
  596. INET_ASSERT(error == ERROR_SUCCESS && // for now, let's see all errors
  597. fsm.m_dwBytesRead - fsm.m_nBytesCopied == dwChunkBytesRead);
  598. fsm.m_dwBufferLeft += (fsm.m_dwBytesRead - fsm.m_nBytesCopied);
  599. fsm.m_dwBytesRead -= (fsm.m_dwBytesRead - fsm.m_nBytesCopied);
  600. fsm.m_dwBufferLeft -= dwChunkBytesWritten;
  601. fsm.m_dwBytesRead += dwChunkBytesWritten;
  602. fsm.m_nBytesCopied += dwChunkBytesWritten;
  603. if ( error != ERROR_SUCCESS )
  604. {
  605. goto quit;
  606. }
  607. // Chunked transfers tell us when to expect EOF
  608. if ( IsDecodingFinished() )
  609. {
  610. fsm.m_bEof = TRUE;
  611. }
  612. else if (fsm.m_dwBytesRead < fsm.m_dwNumberOfBytesToRead &&
  613. !fsm.m_bEof)
  614. {
  615. // read some more
  616. goto read_again;
  617. }
  618. }
  619. } else {
  620. PERF_LOG(PE_TRACE, 0x6121);
  621. DEBUG_PRINT(HTTP,
  622. ERROR,
  623. ("error %d on socket %#x\n",
  624. error,
  625. _Socket->GetSocket()
  626. ));
  627. //
  628. // socket error
  629. //
  630. SetState(HttpRequestStateError);
  631. //
  632. // cause connection to be closed/released
  633. //
  634. fsm.m_bEof = TRUE;
  635. }
  636. done:
  637. //
  638. // only update bytes remaining, EOF and the current stream position values
  639. // if we're returning data. If we just completed reading ReadFileEx data
  640. // then don't update. The 1 byte of ReadFileEx data will be read on the next
  641. // read proper
  642. //
  643. if (HaveReadFileExData()) {
  644. goto quit;
  645. }
  646. //
  647. // whether the data came from the response buffer or the socket, if we have
  648. // a content-length, update the amount of data left to retrieve
  649. //
  650. if (IsChunkEncoding()
  651. && IsDecodingFinished()
  652. && (_QueryBytesAvailable == 0)
  653. && (BufferDataAvailToRead() == 0)) {
  654. fsm.m_bEof = TRUE;
  655. } else if (IsKeepAlive() && IsContentLength()) {
  656. _BytesRemaining -= fsm.m_dwBytesRead;
  657. INET_ASSERT((int)_BytesRemaining >= 0);
  658. //
  659. // if we have read all the entity-body then we can release the keep-alive
  660. // connection, or close the socket
  661. //
  662. if (_BytesRemaining<=0 && ((int)_BytesRemaining>=-2)) {
  663. // We might overshoot by 1 or 2 because of server misinformation.
  664. fsm.m_bEof = TRUE;
  665. }
  666. }
  667. DEBUG_PRINT(HTTP,
  668. INFO,
  669. ("read %d bytes\n",
  670. fsm.m_dwBytesRead
  671. ));
  672. //
  673. // if we reached the end of the connection - either the end of the server
  674. // connection for real, or we received all indicated data on a keep-alive
  675. // connection - then close the connection
  676. //
  677. if (fsm.m_bEof) {
  678. PERF_LOG(PE_TRACE, 0x6122);
  679. //
  680. // if we don't need to keep hold of the connection, release it. In the
  681. // case of multi-part authentication (NTLM) over keep-alive connection
  682. // we need to keep the connection. With Kerberos, we don't need to keep
  683. // the connection.
  684. //
  685. if (GetAuthState() != AUTHSTATE_CHALLENGE) {
  686. DEBUG_PRINT(HTTP,
  687. INFO,
  688. ("end of data - freeing connection %#x (Auth State = %s)\n",
  689. _Socket ? _Socket->GetSocket() : 0,
  690. (GetAuthState() == AUTHSTATE_NONE)
  691. ? "NONE"
  692. : ((GetAuthState() == AUTHSTATE_NEGOTIATE)
  693. ? "NEGOTIATE"
  694. : ((GetAuthState() == AUTHSTATE_CHALLENGE)
  695. ? "CHALLENGE"
  696. : "?"))
  697. ));
  698. CloseConnection(FALSE);
  699. } else {
  700. // AUTHSTATE_CHALLENGE - check if request is through proxy or is kerberos.
  701. // When IsRequestUsingProxy returns TRUE, there are three types of connections possible:
  702. // 1) http request forwarded by the proxy to the server
  703. // 2) connect request to proxy to establish https tunnel
  704. // 3) using https tunnel through proxy to the server
  705. // I believe the various methods return:
  706. //��������������������������������������������� http��� conn.�� tunnel
  707. // IsRequestUsingProxy 1����� 1������� 1
  708. // IsViaProxy������������ 1����� 1������� 0
  709. // IsTunnel������������������������������������ 0��� 1������� 0
  710. // IsTalkingToSecureServerViaProxy������������� 0����� 0������� 1
  711. INET_ASSERT(_pAuthCtx->GetSchemeType() != WINHTTP_AUTH_SCHEME_NEGOTIATE);
  712. if (GetAuthCtx()->GetSchemeType() == WINHTTP_AUTH_SCHEME_KERBEROS)
  713. {
  714. DEBUG_PRINT(HTTP,
  715. INFO,
  716. ("freeing connection - kerberos and auth state challenge\n"
  717. ));
  718. CloseConnection(FALSE);
  719. }
  720. else if (IsRequestUsingProxy()
  721. && !(IsTunnel() || IsTalkingToSecureServerViaProxy())
  722. && (_pAuthCtx->GetFlags() & PLUGIN_AUTH_FLAGS_KEEP_ALIVE_NOT_REQUIRED)
  723. && !_pAuthCtx->_fIsProxy)
  724. {
  725. // Ordinarily, if the auth state is AUTHSTATE_CHALLENGE we wish to keep
  726. // the current connection open (keep alive) so that the response will go
  727. // out on the same socket. NTLM, which requires keep-alive, does not
  728. // work when going through a proxy. In the case that the proxy does not return keep-alive with the
  729. // challenge (Catapult appears to be the only proxy that does) we want to
  730. // close the socket to ensure that it is not subsequently used for the response.
  731. DEBUG_PRINT(HTTP,
  732. INFO,
  733. ("freeing connection - auth state challenge\n"
  734. ));
  735. CloseConnection(FALSE);
  736. }
  737. else
  738. {
  739. // Keep alive required - don't close socket.
  740. DEBUG_PRINT(HTTP,
  741. INFO,
  742. ("not freeing connection - auth state challenge\n"
  743. ));
  744. }
  745. }
  746. //
  747. // there is no more data to be received on this object
  748. //
  749. SetData(FALSE);
  750. //
  751. // this object can now be re-used
  752. //
  753. SetState(HttpRequestStateReopen);
  754. }
  755. quit:
  756. //
  757. // update the amount of data returned then we're outta here
  758. //
  759. *fsm.m_lpdwNumberOfBytesRead = fsm.m_dwBytesRead;
  760. if (error != ERROR_IO_PENDING) {
  761. fsm.SetDone();
  762. }
  763. quit_pending:
  764. PERF_LOG(PE_TRACE, 0x6002);
  765. DEBUG_LEAVE(error);
  766. return error;
  767. }
  768. DWORD
  769. HTTP_REQUEST_HANDLE_OBJECT::QueryDataAvailable(
  770. OUT LPDWORD lpdwNumberOfBytesAvailable
  771. )
  772. /*++
  773. Routine Description:
  774. Determines how much data is available to be read by the caller
  775. BUGBUG - need cache case
  776. Arguments:
  777. lpdwNumberOfBytesAvailable - returned number of bytes available
  778. Return Value:
  779. DWORD
  780. Success - ERROR_SUCCESS
  781. Failure - ERROR_WINHTTP_INCORRECT_HANDLE_STATE
  782. --*/
  783. {
  784. DEBUG_ENTER((DBG_HTTP,
  785. Dword,
  786. "HTTP_REQUEST_HANDLE_OBJECT::QueryDataAvailable",
  787. "%#x",
  788. lpdwNumberOfBytesAvailable
  789. ));
  790. DWORD error = DoFsm(New CFsm_HttpQueryAvailable(lpdwNumberOfBytesAvailable,
  791. this
  792. ));
  793. DEBUG_LEAVE(error);
  794. return error;
  795. }
  796. DWORD
  797. CFsm_HttpQueryAvailable::RunSM(
  798. IN CFsm * Fsm
  799. )
  800. /*++
  801. Routine Description:
  802. description-of-function.
  803. Arguments:
  804. Fsm -
  805. Return Value:
  806. DWORD
  807. --*/
  808. {
  809. DEBUG_ENTER((DBG_HTTP,
  810. Dword,
  811. "CFsm_HttpQueryAvailable::RunSM",
  812. "%#x",
  813. Fsm
  814. ));
  815. DWORD error;
  816. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  817. CFsm_HttpQueryAvailable * stateMachine = (CFsm_HttpQueryAvailable *)Fsm;
  818. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
  819. switch (Fsm->GetState()) {
  820. case FSM_STATE_INIT:
  821. case FSM_STATE_CONTINUE:
  822. error = pRequest->QueryAvailable_Fsm(stateMachine);
  823. break;
  824. default:
  825. error = ERROR_WINHTTP_INTERNAL_ERROR;
  826. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  827. INET_ASSERT(FALSE);
  828. break;
  829. }
  830. DEBUG_LEAVE(error);
  831. return error;
  832. }
  833. DWORD
  834. HTTP_REQUEST_HANDLE_OBJECT::QueryAvailable_Fsm(
  835. IN CFsm_HttpQueryAvailable * Fsm
  836. )
  837. /*++
  838. Routine Description:
  839. description-of-function.
  840. Arguments:
  841. Fsm -
  842. Return Value:
  843. DWORD
  844. --*/
  845. {
  846. DEBUG_ENTER((DBG_HTTP,
  847. Dword,
  848. "QueryAvailable_Fsm",
  849. "%#x",
  850. Fsm
  851. ));
  852. CFsm_HttpQueryAvailable & fsm = *Fsm;
  853. DWORD error = fsm.GetError();
  854. DWORD bytesAvailable = 0;
  855. if (fsm.GetState() == FSM_STATE_CONTINUE) {
  856. goto fsm_continue;
  857. }
  858. INET_ASSERT(fsm.GetState() == FSM_STATE_INIT);
  859. //
  860. // the handle must be readable
  861. //
  862. if (!CheckReceiveResponseState() || !IsValidHttpState(READ)) {
  863. error = ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
  864. goto quit;
  865. }
  866. fsm.m_bEof = FALSE;
  867. //
  868. // error must be ERROR_SUCCESS - we just read it out of FSM & didn't jump
  869. // anywhere
  870. //
  871. INET_ASSERT(error == ERROR_SUCCESS);
  872. //
  873. // first check if there is data to receive at all
  874. //
  875. if (IsData()) {
  876. //
  877. // if there's buffered data still available from receiving the headers,
  878. // then return that length, else query the information from the socket
  879. //
  880. if (IsBufferedData()) {
  881. bytesAvailable = BufferDataAvailToRead();
  882. DEBUG_PRINT(HTTP,
  883. INFO,
  884. ("%d bytes available in buffer\n",
  885. bytesAvailable
  886. ));
  887. } else if (_Socket != NULL) {
  888. //
  889. // the rest of the data must be read from the socket
  890. //
  891. BOOL checkSocket;
  892. if (IsKeepAlive() && IsContentLength()) {
  893. checkSocket = ((int)_BytesInSocket > 0) ? TRUE : FALSE;
  894. } else if (IsChunkEncoding()) {
  895. checkSocket = !IsDecodingFinished();
  896. } else {
  897. checkSocket = TRUE;
  898. }
  899. if (checkSocket) {
  900. if (_QueryBuffer != NULL) {
  901. bytesAvailable = _QueryBytesAvailable;
  902. checkSocket = (bytesAvailable == 0) ? TRUE : FALSE;
  903. } else {
  904. error = _Socket->AllocateQueryBuffer(&_QueryBuffer,
  905. &_QueryBufferLength
  906. );
  907. if (error != ERROR_SUCCESS) {
  908. checkSocket = FALSE;
  909. }
  910. }
  911. } else if (IsKeepAlive() && IsContentLength() && (_BytesRemaining == 0)) {
  912. fsm.m_bEof = TRUE;
  913. } else if (IsChunkEncoding() && IsDecodingFinished()) {
  914. fsm.m_bEof = TRUE;
  915. }
  916. if (checkSocket) {
  917. INET_ASSERT(_Socket->IsValid());
  918. INET_ASSERT(_QueryBytesAvailable == 0);
  919. //
  920. // reset the query buffer offset
  921. //
  922. _QueryOffset = 0;
  923. //
  924. // don't create another FSM just for the DataAvailable2 wrapper.
  925. // If it ever becomes more than a call to Receive() then create
  926. // an FSM
  927. //
  928. fsm.m_lpBuffer = _QueryBuffer;
  929. fsm.m_dwBufferLength = (IsKeepAlive() && IsContentLength())
  930. ? min(_BytesRemaining, _QueryBufferLength)
  931. : _QueryBufferLength;
  932. fsm.m_dwBufferLeft = fsm.m_dwBufferLength;
  933. //INET_ASSERT(fsm.m_dwBufferLeft <= _BytesRemaining);
  934. if (IsBadNSServer() && !IsConnCloseResponse()) {
  935. SetBadNSReceiveTimeout();
  936. }
  937. error = _Socket->Receive(&fsm.m_lpBuffer,
  938. &fsm.m_dwBufferLength,
  939. &fsm.m_dwBufferLeft, // don't care about this
  940. &_QueryBytesAvailable,
  941. 0,
  942. 0,
  943. &fsm.m_bEof
  944. );
  945. if (error == ERROR_IO_PENDING) {
  946. goto done;
  947. }
  948. fsm_continue:
  949. if ((error == ERROR_WINHTTP_TIMEOUT) && IsBadNSServer()) {
  950. DEBUG_PRINT(HTTP,
  951. INFO,
  952. ("Bad NS server: Closing connection %#x/%d on timeout\n",
  953. _Socket ? _Socket->GetSocket() : -1,
  954. _Socket ? _Socket->GetSourcePort() : -1
  955. ));
  956. CloseConnection(TRUE);
  957. _QueryBytesAvailable = 0;
  958. error = ERROR_SUCCESS;
  959. }
  960. if (error == ERROR_SUCCESS) {
  961. if ( IsChunkEncoding() && (_QueryBytesAvailable != 0))
  962. {
  963. DWORD dwChunkBytesRead = 0;
  964. DWORD dwChunkBytesWritten = 0;
  965. error = _ResponseFilterList.Decode((LPBYTE)_QueryBuffer,
  966. _QueryBytesAvailable,
  967. NULL,
  968. NULL,
  969. &dwChunkBytesRead,
  970. &dwChunkBytesWritten);
  971. _QueryBytesAvailable = dwChunkBytesWritten;
  972. INET_ASSERT(error == ERROR_SUCCESS); // I want to see this.
  973. if ( error != ERROR_SUCCESS )
  974. {
  975. goto quit;
  976. }
  977. }
  978. bytesAvailable = _QueryBytesAvailable;
  979. //
  980. // note the amount of data that is available immediately.
  981. // This allows e.g. async InternetReadFile() to complete
  982. // synchronously if the next request is for <= bytesAvailable
  983. //
  984. //SetAvailableDataLength(bytesAvailable);
  985. DEBUG_PRINT(HTTP,
  986. INFO,
  987. ("%d bytes available in socket %#x\n",
  988. bytesAvailable,
  989. (_Socket ? _Socket->GetSocket() : 0)
  990. ));
  991. if ((bytesAvailable == 0)
  992. && (IsChunkEncoding() ? IsDecodingFinished() : TRUE)) {
  993. fsm.m_bEof = TRUE;
  994. }
  995. if (IsKeepAlive() && IsContentLength()) {
  996. _BytesInSocket -= bytesAvailable;
  997. INET_ASSERT((int)_BytesInSocket >= 0);
  998. if ((int)_BytesInSocket < 0) {
  999. _BytesInSocket = 0;
  1000. }
  1001. }
  1002. }
  1003. }
  1004. } else {
  1005. //
  1006. // all data read from socket & socket released
  1007. //
  1008. INET_ASSERT(error == ERROR_SUCCESS);
  1009. INET_ASSERT(bytesAvailable == 0);
  1010. DEBUG_PRINT(HTTP,
  1011. INFO,
  1012. ("no socket\n"
  1013. ));
  1014. fsm.m_bEof = TRUE;
  1015. }
  1016. } else {
  1017. INET_ASSERT(error == ERROR_SUCCESS);
  1018. //
  1019. // we may have already removed all the data from the socket
  1020. //
  1021. DEBUG_PRINT(HTTP,
  1022. INFO,
  1023. ("all data has been read\n"
  1024. ));
  1025. fsm.m_bEof = TRUE;
  1026. }
  1027. quit:
  1028. *fsm.m_lpdwNumberOfBytesAvailable = bytesAvailable;
  1029. //
  1030. // if we have reached the end of the data then we can release the connection
  1031. //
  1032. /*
  1033. if (fsm.m_bEof || (bytesAvailable >= _BytesRemaining)) {
  1034. if (_Socket != NULL) {
  1035. CloseConnection(FALSE);
  1036. }
  1037. }
  1038. */
  1039. if (fsm.m_bEof) {
  1040. if (_Socket != NULL) {
  1041. CloseConnection(FALSE);
  1042. }
  1043. }
  1044. done:
  1045. if (error != ERROR_IO_PENDING) {
  1046. fsm.SetDone();
  1047. }
  1048. DEBUG_LEAVE(error);
  1049. return error;
  1050. }
  1051. DWORD
  1052. HTTP_REQUEST_HANDLE_OBJECT::DrainResponse(
  1053. OUT LPBOOL lpbDrained
  1054. )
  1055. /*++
  1056. Routine Description:
  1057. Receives any remaining response data into the buffer we allocated for the
  1058. headers. Used in redirection: if the server returns some HTML page (e.g.)
  1059. with the redirection response, we give the app a chance to read it. This
  1060. way, we allow the app to retrieve the data immediately during the status
  1061. callback in which we indicate that the request has been redirected
  1062. Arguments:
  1063. lpbDrained - TRUE if we really drained the socket else FALSE
  1064. Return Value:
  1065. DWORD
  1066. Success - ERROR_SUCCESS
  1067. Failure - WSA error mapped to ERROR_WINHTTP_XXX
  1068. --*/
  1069. {
  1070. DEBUG_ENTER((DBG_HTTP,
  1071. Dword,
  1072. "HTTP_REQUEST_HANDLE_OBJECT::DrainResponse",
  1073. "%#x",
  1074. lpbDrained
  1075. ));
  1076. DWORD error = DoFsm(New CFsm_DrainResponse(lpbDrained, this));
  1077. DEBUG_LEAVE(error);
  1078. return error;
  1079. }
  1080. DWORD
  1081. CFsm_DrainResponse::RunSM(
  1082. IN CFsm * Fsm
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. description-of-function.
  1087. Arguments:
  1088. Fsm -
  1089. Return Value:
  1090. DWORD
  1091. --*/
  1092. {
  1093. DEBUG_ENTER((DBG_HTTP,
  1094. Dword,
  1095. "CFsm_DrainResponse::RunSM",
  1096. "%#x",
  1097. Fsm
  1098. ));
  1099. DWORD error;
  1100. HTTP_REQUEST_HANDLE_OBJECT * pRequest;
  1101. CFsm_DrainResponse * stateMachine = (CFsm_DrainResponse *)Fsm;
  1102. pRequest = (HTTP_REQUEST_HANDLE_OBJECT *)Fsm->GetContext();
  1103. switch (Fsm->GetState()) {
  1104. case FSM_STATE_INIT:
  1105. case FSM_STATE_CONTINUE:
  1106. error = pRequest->DrainResponse_Fsm(stateMachine);
  1107. break;
  1108. default:
  1109. error = ERROR_WINHTTP_INTERNAL_ERROR;
  1110. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  1111. INET_ASSERT(FALSE);
  1112. break;
  1113. }
  1114. DEBUG_LEAVE(error);
  1115. return error;
  1116. }
  1117. DWORD
  1118. HTTP_REQUEST_HANDLE_OBJECT::DrainResponse_Fsm(
  1119. IN CFsm_DrainResponse * Fsm
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. description-of-function.
  1124. Arguments:
  1125. Fsm -
  1126. Return Value:
  1127. DWORD
  1128. --*/
  1129. {
  1130. DEBUG_ENTER((DBG_HTTP,
  1131. Dword,
  1132. "HTTP_REQUEST_HANDLE_OBJECT::DrainResponse_Fsm",
  1133. "%#x",
  1134. Fsm
  1135. ));
  1136. CFsm_DrainResponse & fsm = *Fsm;
  1137. DWORD error = fsm.GetError();
  1138. BOOL drainIt = FALSE;
  1139. if (error != ERROR_SUCCESS) {
  1140. goto quit;
  1141. }
  1142. if (fsm.GetState() == FSM_STATE_CONTINUE) {
  1143. drainIt = TRUE;
  1144. goto fsm_continue;
  1145. }
  1146. PERF_LOG(PE_TRACE, 0x8001);
  1147. drainIt = TRUE;
  1148. //
  1149. // if the socket is already closed, we can't drain it
  1150. //
  1151. if ((_Socket == NULL) || !_Socket->IsValid()) {
  1152. drainIt = FALSE;
  1153. } else if (IsWantKeepAlive()) {
  1154. //
  1155. // IIS 1.0 has a bug where it can return a failure indication to a
  1156. // request that was made using a keep-alive connection. The response
  1157. // doesn't contain a keep-alive header but the server has left open the
  1158. // connection AND it has returned us fewer bytes than was claimed in
  1159. // the content-length header. If we try to drain the response buffer at
  1160. // this point, we will wait a long time waiting for the server to send
  1161. // us the non-existent additional bytes. Therefore, if we are talking
  1162. // to an IIS 1.0 server, we don't drain the response buffer
  1163. //
  1164. LPSTR lpszServerBuf;
  1165. DWORD serverBufferLength;
  1166. if (_ResponseHeaders.LockHeaders())
  1167. {
  1168. error = FastQueryResponseHeader(HTTP_QUERY_SERVER,
  1169. (LPVOID *)&lpszServerBuf,
  1170. &serverBufferLength,
  1171. 0
  1172. );
  1173. if (error == ERROR_SUCCESS) {
  1174. #define IIS "Microsoft-IIS/"
  1175. #define IIS_LEN (sizeof(IIS) - 1)
  1176. #define PWS "Microsoft-PWS/"
  1177. #define PWS_LEN (sizeof(PWS) - 1)
  1178. #define PWS95 "Microsoft-PWS-95/"
  1179. #define PWS95_LEN (sizeof(PWS95) - 1)
  1180. #define IIS10 "Microsoft-Internet-Information-Server/"
  1181. #define IIS10_LEN (sizeof(IIS10) - 1)
  1182. if ((serverBufferLength > IIS_LEN)
  1183. && !strnicmp(lpszServerBuf, IIS, IIS_LEN)) {
  1184. int major_num = 0;
  1185. for (DWORD i = IIS_LEN; i < serverBufferLength; ++i) {
  1186. char ch = lpszServerBuf[i];
  1187. if (isdigit(ch)) {
  1188. major_num = major_num * 10 + (int)(ch - '0');
  1189. } else {
  1190. break;
  1191. }
  1192. }
  1193. if (major_num < 4) {
  1194. drainIt = FALSE;
  1195. }
  1196. } else if (IsBadNSServer()) {
  1197. drainIt = FALSE;
  1198. } else if (((serverBufferLength > IIS10_LEN)
  1199. && !strncmp(lpszServerBuf, IIS10, IIS10_LEN))
  1200. || ((serverBufferLength > PWS_LEN)
  1201. && !strncmp(lpszServerBuf, PWS, PWS_LEN))
  1202. || ((serverBufferLength > PWS95_LEN)
  1203. && !strncmp(lpszServerBuf, PWS95, PWS95_LEN))) {
  1204. drainIt = FALSE;
  1205. }
  1206. }
  1207. _ResponseHeaders.UnlockHeaders();
  1208. }
  1209. }
  1210. error = ERROR_SUCCESS;
  1211. if (drainIt) {
  1212. fsm.m_dwAsyncFlags = IsAsyncHandle() ? SF_WAIT : 0;
  1213. fsm.m_dwAmountToRead = IsContentLength() ? _BytesInSocket : (DWORD)-1;
  1214. //DWORD bufferLeft = _ResponseBufferLength - _BytesReceived;
  1215. fsm.m_dwBufferLeft = min(fsm.m_dwAmountToRead, _ResponseBufferLength - _BytesReceived);
  1216. if (IsChunkEncoding() && IsDecodingFinished()) {
  1217. fsm.m_dwAmountToRead = 0;
  1218. fsm.m_bEof = TRUE;
  1219. INET_ASSERT(fsm.m_dwBytesReceived == 0);
  1220. }
  1221. //
  1222. // either receive the amount specified in the "Content-Length" header, or
  1223. // receive until we hit the end of the connection. We may have already
  1224. // received the entire response
  1225. //
  1226. while ((fsm.m_dwAmountToRead != 0) && !fsm.m_bEof && (error == ERROR_SUCCESS)) {
  1227. fsm.m_dwPreviousBytesReceived = _BytesReceived;
  1228. //
  1229. // receive the rest of the data. We are assuming here that it is a
  1230. // couple of K at the most. Notice that we don't care to make status
  1231. // callbacks to the app while we are doing this
  1232. //
  1233. //INET_ASSERT(fsm.m_dwBufferLeft <= _BytesRemaining);
  1234. error = _Socket->Receive((LPVOID *)&_ResponseBuffer,
  1235. &_ResponseBufferLength,
  1236. &fsm.m_dwBufferLeft,
  1237. &_BytesReceived,
  1238. 0, // dwExtraSpace
  1239. SF_EXPAND
  1240. | SF_COMPRESS
  1241. | fsm.m_dwAsyncFlags,
  1242. &fsm.m_bEof
  1243. );
  1244. if (error == ERROR_IO_PENDING) {
  1245. goto quit;
  1246. }
  1247. fsm_continue:
  1248. if (error == ERROR_SUCCESS) {
  1249. DWORD nRead = _BytesReceived - fsm.m_dwPreviousBytesReceived;
  1250. if (IsContentLength()) {
  1251. fsm.m_dwAmountToRead -= nRead;
  1252. INET_ASSERT((int)fsm.m_dwAmountToRead >= 0);
  1253. _BytesInSocket -= nRead;
  1254. INET_ASSERT((int)_BytesInSocket >= 0);
  1255. if (IsKeepAlive()) {
  1256. _BytesRemaining -= nRead;
  1257. INET_ASSERT((int)_BytesRemaining >= 0);
  1258. //
  1259. // if we have read all the entity-body then we can
  1260. // release the keep-alive connection, or close the
  1261. // socket
  1262. //
  1263. //
  1264. // BUGBUG - put back post-ie30a
  1265. //
  1266. //if (_BytesRemaining == 0) {
  1267. // fsm.m_bEof = TRUE;
  1268. //}
  1269. }
  1270. }
  1271. if ( IsChunkEncoding() )
  1272. {
  1273. DWORD dwChunkBytesRead = 0;
  1274. DWORD dwChunkBytesWritten = 0;
  1275. INET_ASSERT(!IsContentLength());
  1276. error = _ResponseFilterList.Decode(
  1277. _ResponseBuffer + fsm.m_dwPreviousBytesReceived,
  1278. nRead,
  1279. NULL,
  1280. NULL,
  1281. &dwChunkBytesRead,
  1282. &dwChunkBytesWritten
  1283. );
  1284. nRead = dwChunkBytesWritten;
  1285. _BytesReceived = nRead + fsm.m_dwPreviousBytesReceived;
  1286. INET_ASSERT(error == ERROR_SUCCESS); // I want to see this happen.
  1287. if ( error != ERROR_SUCCESS )
  1288. {
  1289. break;
  1290. }
  1291. if ( IsDecodingFinished() )
  1292. {
  1293. fsm.m_bEof = TRUE;
  1294. break;
  1295. }
  1296. }
  1297. fsm.m_dwBytesReceived += nRead;
  1298. fsm.m_dwPreviousBytesReceived = _BytesReceived;
  1299. }
  1300. }
  1301. }
  1302. if (error == ERROR_SUCCESS) {
  1303. //
  1304. // update the amount of data immediately available to the caller
  1305. //
  1306. IncreaseAvailableDataLength(fsm.m_dwBytesReceived);
  1307. //
  1308. // and set the end-of-file indication in the top level handle object
  1309. //
  1310. SetEndOfFile();
  1311. //
  1312. // there is no more data to be received on this HTTP object
  1313. //
  1314. //SetData(FALSE);
  1315. //
  1316. // this object can now be re-used
  1317. //
  1318. SetState(HttpRequestStateReopen);
  1319. }
  1320. //
  1321. // return indication that we drained the socket
  1322. //
  1323. DEBUG_PRINT(HTTP,
  1324. INFO,
  1325. ("returning *lpbDrained = %B\n",
  1326. drainIt
  1327. ));
  1328. quit:
  1329. if (error != ERROR_IO_PENDING) {
  1330. fsm.SetDone();
  1331. *fsm.m_lpbDrained = drainIt;
  1332. }
  1333. PERF_LOG(PE_TRACE, 0x8002);
  1334. DEBUG_LEAVE(error);
  1335. return error;
  1336. }
  1337. VOID
  1338. HTTP_REQUEST_HANDLE_OBJECT::SetBadNSReceiveTimeout(
  1339. VOID
  1340. )
  1341. {
  1342. DEBUG_ENTER((DBG_HTTP,
  1343. None,
  1344. "HTTP_REQUEST_HANDLE_OBJECT::SetBadNSReceiveTimeout",
  1345. NULL
  1346. ));
  1347. if ((_Socket != NULL)
  1348. && !IsContentLength()
  1349. && !IsChunkEncoding()) {
  1350. CServerInfo * pServerInfo = GetServerInfo();
  1351. if (pServerInfo) {
  1352. DWORD timeout = max(5000, 5 * pServerInfo->GetRTT());
  1353. _Socket->SetTimeout(RECEIVE_TIMEOUT, timeout);
  1354. SetTimeout(WINHTTP_OPTION_RECEIVE_TIMEOUT, timeout);
  1355. }
  1356. }
  1357. DEBUG_LEAVE(0);
  1358. }