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.

6243 lines
160 KiB

  1. /*++
  2. Copyright (c) 1995-1997 Microsoft Corporation
  3. Module Name:
  4. icsocket.cxx
  5. Abstract:
  6. Contains sockets functions and ICSocket methods
  7. Contents:
  8. ContainingICSocket
  9. MapNetAddressToName
  10. ICSocket::ICSocket
  11. ICSocket::~ICSocket
  12. ICSocket::Destroy
  13. ICSocket::Reference
  14. ICSocket::Dereference
  15. ICSocket::EnableSocks
  16. ICSocket::Connect
  17. CFsm_SocketConnect::RunSM
  18. ICSocket::Connect_Start
  19. ICSocket::Connect_Continue
  20. ICSocket::Connect_Error
  21. ICSocket::Connect_Finish
  22. ICSocket::SocksConnect
  23. ICSocket::Disconnect
  24. ICSocket::Close
  25. ICSocket::Abort
  26. ICSocket::Shutdown
  27. ICSocket::IsReset
  28. ICSocket::SetTimeout
  29. ICSocket::SetLinger
  30. ICSocket::SetNonBlockingMode
  31. ICSocket::GetBufferLength(SOCKET_BUFFER_ID)
  32. ICSocket::GetBufferLength(SOCKET_BUFFER_ID, LPDWORD)
  33. ICSocket::SetBufferLength
  34. ICSocket::SetSendCoalescing
  35. SetSourcePort
  36. ICSocket::Send
  37. CFsm_SocketSend::RunSM
  38. ICSocket::Send_Start
  39. ICSocket::SendTo
  40. ICSocket::Receive
  41. CFsm_SocketReceive::RunSM
  42. ICSocket::Receive_Start
  43. ICSocket::Receive_Continue
  44. ICSocket::AllocateQueryBuffer
  45. //ICSocket::FreeQueryBuffer
  46. //ICSocket::ReceiveFrom
  47. ICSocket::DataAvailable
  48. //ICSocket::DataAvailable2
  49. ICSocket::WaitForReceive
  50. //ICSocket::GetBytesAvailable
  51. //ICSocket::CreateSocket
  52. ICSocket::GetSockName
  53. ICSocket::Listen
  54. ICSocket::DirectConnect
  55. ICSocket::SelectAccept
  56. Author:
  57. Richard L Firth (rfirth) 08-Apr-1997
  58. Environment:
  59. Win32 user mode
  60. Revision History:
  61. 08-Apr-1997 rfirth
  62. Created from ixport.cxx
  63. --*/
  64. #include <wininetp.h>
  65. #include <perfdiag.hxx>
  66. //
  67. // private prototypes
  68. //
  69. //
  70. // functions
  71. //
  72. #if INET_DEBUG
  73. PRIVATE LPSTR MapFamily(int family) {
  74. switch (family) {
  75. case AF_UNSPEC: return "AF_UNSPEC";
  76. case AF_UNIX: return "AF_UNIX";
  77. case AF_INET: return "AF_INET";
  78. case AF_IMPLINK: return "AF_IMPLINK";
  79. case AF_PUP: return "AF_PUP";
  80. case AF_CHAOS: return "AF_CHAOS";
  81. case AF_IPX: return "AF_IPX";
  82. case AF_OSI: return "AF_OSI";
  83. case AF_ECMA: return "AF_ECMA";
  84. case AF_DATAKIT: return "AF_DATAKIT";
  85. case AF_CCITT: return "AF_CCITT";
  86. case AF_SNA: return "AF_SNA";
  87. case AF_DECnet: return "AF_DECnet";
  88. case AF_DLI: return "AF_DLI";
  89. case AF_LAT: return "AF_LAT";
  90. case AF_HYLINK: return "AF_HYLINK";
  91. case AF_APPLETALK: return "AF_APPLETALK";
  92. case AF_NETBIOS: return "AF_NETBIOS";
  93. #if defined(AF_VOICEVIEW)
  94. case AF_VOICEVIEW: return "AF_VOICEVIEW";
  95. #endif /* AF_VOICEVIEW */
  96. #if defined(AF_FIREFOX)
  97. case AF_FIREFOX: return "AF_FIREFOX";
  98. #endif /* AF_FIREFOX */
  99. #if defined(AF_UNKNOWN1)
  100. case AF_UNKNOWN1: return "AF_UNKNOWN1";
  101. #endif /* AF_UNKNOWN1 */
  102. #if defined(AF_BAN)
  103. case AF_BAN: return "AF_BAN";
  104. #endif /* AF_BAN */
  105. #if defined(AF_INET6)
  106. case AF_INET6: return "AF_INET6";
  107. #endif /* AF_INET6 */
  108. }
  109. return "?";
  110. }
  111. PRIVATE LPSTR MapSock(int sock) {
  112. switch (sock) {
  113. case SOCK_STREAM: return "SOCK_STREAM";
  114. case SOCK_DGRAM: return "SOCK_DGRAM";
  115. case SOCK_RAW: return "SOCK_RAW";
  116. case SOCK_RDM: return "SOCK_RDM";
  117. case SOCK_SEQPACKET: return "SOCK_SEQPACKET";
  118. }
  119. return "?";
  120. }
  121. PRIVATE LPSTR MapProto(int proto) {
  122. switch (proto) {
  123. case IPPROTO_IP: return "IPPROTO_IP";
  124. case IPPROTO_ICMP: return "IPPROTO_ICMP";
  125. case IPPROTO_IGMP: return "IPPROTO_IGMP";
  126. case IPPROTO_GGP: return "IPPROTO_GGP";
  127. case IPPROTO_TCP: return "IPPROTO_TCP";
  128. case IPPROTO_PUP: return "IPPROTO_PUP";
  129. case IPPROTO_UDP: return "IPPROTO_UDP";
  130. case IPPROTO_IDP: return "IPPROTO_IDP";
  131. case IPPROTO_ND: return "IPPROTO_ND";
  132. }
  133. return "?";
  134. }
  135. #endif // INET_DEBUG
  136. ICSocket *
  137. ContainingICSocket(
  138. LPVOID lpAddress
  139. )
  140. /*++
  141. Routine Description:
  142. Returns address of start of ICSocket (i.e. vtable) given address of list
  143. Arguments:
  144. lpAddress - address of m_List part of ICSocket
  145. Return Value:
  146. ICSocket * - address of start of ICSocket object (also ICSecureSocket)
  147. --*/
  148. {
  149. return CONTAINING_RECORD(lpAddress, ICSocket, m_List);
  150. }
  151. //
  152. // ICSocket methods
  153. //
  154. ICSocket::ICSocket(
  155. VOID
  156. )
  157. /*++
  158. Routine Description:
  159. ICSocket constructor
  160. Arguments:
  161. None.
  162. Return Value:
  163. None.
  164. --*/
  165. {
  166. DEBUG_ENTER((DBG_OBJECTS,
  167. None,
  168. "ICSocket::ICSocket",
  169. "{%#x}",
  170. this
  171. ));
  172. SIGN_ICSOCKET();
  173. m_List.Flink = NULL;
  174. m_List.Blink = NULL;
  175. m_dwTimeout = 0;
  176. m_fTimeoutWraps = 0;
  177. m_Socket = INVALID_SOCKET;
  178. m_dwFlags = 0;
  179. m_bAborted = FALSE;
  180. m_SocksAddress = 0;
  181. m_SocksPort = 0;
  182. m_ReferenceCount = 1;
  183. _pCurrentFsm = NULL;
  184. _lpWrapOverlappedSend = NULL;
  185. _lpWrapOverlappedRecv = NULL;
  186. m_fIsSecureSocket = FALSE; // ICSecureSocket will set this to TRUE
  187. DEBUG_LEAVE(0);
  188. }
  189. ICSocket::~ICSocket()
  190. /*++
  191. Routine Description:
  192. ICSocket destructor. Virtual function
  193. Arguments:
  194. None.
  195. Return Value:
  196. None.
  197. --*/
  198. {
  199. DEBUG_ENTER((DBG_OBJECTS,
  200. None,
  201. "ICSocket::~ICSocket",
  202. "{%#x [sock=%#x, port=%d, ref=%d]}",
  203. this,
  204. GetSocket(),
  205. GetSourcePort(),
  206. ReferenceCount()
  207. ));
  208. CHECK_ICSOCKET();
  209. INET_ASSERT(!IsOnList());
  210. INET_ASSERT(m_ReferenceCount == 0);
  211. if (IsOpen()) {
  212. Close();
  213. }
  214. if (_lpWrapOverlappedSend)
  215. _lpWrapOverlappedSend->Dereference();
  216. if (_lpWrapOverlappedRecv)
  217. _lpWrapOverlappedRecv->Dereference();
  218. DEBUG_LEAVE(0);
  219. }
  220. VOID
  221. ICSocket::Destroy(
  222. VOID
  223. )
  224. /*++
  225. Routine Description:
  226. description-of-function.
  227. Arguments:
  228. None.
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. DEBUG_ENTER((DBG_OBJECTS,
  234. None,
  235. "ICSocket::Destroy",
  236. "{%#x [%#x/%d]}",
  237. this,
  238. GetSocket(),
  239. GetSourcePort()
  240. ));
  241. INET_ASSERT(ReferenceCount() == 1);
  242. m_ReferenceCount = 0;
  243. delete this;
  244. DEBUG_LEAVE(0);
  245. }
  246. VOID
  247. ICSocket::Reference(
  248. VOID
  249. )
  250. /*++
  251. Routine Description:
  252. Just increases the reference count
  253. Arguments:
  254. None.
  255. Return Value:
  256. None.
  257. --*/
  258. {
  259. CHECK_ICSOCKET();
  260. InterlockedIncrement(&m_ReferenceCount);
  261. }
  262. BOOL
  263. ICSocket::Dereference(
  264. VOID
  265. )
  266. /*++
  267. Routine Description:
  268. Reduces the reference count. If it goes to zero, the object is deleted
  269. Arguments:
  270. None.
  271. Return Value:
  272. BOOL
  273. TRUE - object deleted
  274. FALSE - object still alive
  275. --*/
  276. {
  277. CHECK_ICSOCKET();
  278. if (InterlockedDecrement(&m_ReferenceCount) == 0) {
  279. INET_ASSERT(m_ReferenceCount == 0);
  280. delete this;
  281. return TRUE;
  282. }
  283. return FALSE;
  284. }
  285. PRIVATE
  286. DWORD
  287. ICSocket::EnableSocks(
  288. IN LPSTR lpSocksHost,
  289. IN INTERNET_PORT ipSocksPort
  290. )
  291. /*++
  292. Routine Description:
  293. Set SOCKS gateway IP address and port in this socket object
  294. Arguments:
  295. lpSocksHost - IP address or host name of SOCKS host
  296. ipSocksPort - port address of SOCKS host
  297. Return Value:
  298. DWORD
  299. Success - ERROR_SUCCESS
  300. Failure - ERROR_WINHTTP_NAME_NOT_RESOLVED
  301. failed to resolve SOCKS host name
  302. --*/
  303. {
  304. DEBUG_ENTER((DBG_SOCKETS,
  305. Dword,
  306. "ICSocket::EnableSocks",
  307. "{%#x/%d} %q, %d",
  308. GetSocket(),
  309. GetSourcePort(),
  310. lpSocksHost,
  311. ipSocksPort
  312. ));
  313. DWORD error = ERROR_SUCCESS;
  314. m_SocksPort = ipSocksPort;
  315. m_SocksAddress = _I_inet_addr(lpSocksHost);
  316. if (m_SocksAddress == INADDR_NONE) { // 0xffffffff
  317. LPHOSTENT lpHostent = _I_gethostbyname(lpSocksHost);
  318. if (lpHostent != NULL) {
  319. m_SocksAddress = **(LPDWORD*)&lpHostent->h_addr_list[0];
  320. } else {
  321. m_SocksAddress = 0;
  322. error = ERROR_WINHTTP_NAME_NOT_RESOLVED;
  323. }
  324. }
  325. DEBUG_PRINT(SOCKETS,
  326. INFO,
  327. ("SOCKS address = %d.%d.%d.%d:%d\n",
  328. ((BYTE*)&m_SocksAddress)[0] & 0xff,
  329. ((BYTE*)&m_SocksAddress)[1] & 0xff,
  330. ((BYTE*)&m_SocksAddress)[2] & 0xff,
  331. ((BYTE*)&m_SocksAddress)[3] & 0xff,
  332. m_SocksPort
  333. ));
  334. DEBUG_LEAVE(error);
  335. return error;
  336. }
  337. DWORD
  338. ICSocket::AssociateWithCompletionPort(
  339. VOID
  340. )
  341. {
  342. DEBUG_ENTER((DBG_SOCKETS,
  343. Dword,
  344. "ICSocket::AssociateWithCompletionPort",
  345. "{%#x [%#x]} socketflags=%#x, completionport=%d",
  346. this,
  347. m_Socket,
  348. m_dwFlags,
  349. g_hCompletionPort
  350. ));
  351. DWORD dwError;
  352. SOCKET sock = m_Socket;
  353. if (sock != INVALID_SOCKET)
  354. {
  355. HANDLE hCompPort = CreateIoCompletionPort( (HANDLE)sock,
  356. g_hCompletionPort,
  357. (ULONG_PTR)this,
  358. g_cNumIOCPThreads );
  359. INET_ASSERT ((hCompPort == g_hCompletionPort)
  360. || !hCompPort);
  361. if (hCompPort)
  362. {
  363. dwError = ERROR_SUCCESS;
  364. m_dwFlags |= SF_OVERLAPPED;
  365. }
  366. else
  367. {
  368. dwError = GetLastError();
  369. //informational INET_ASSERT (FALSE);
  370. }
  371. }
  372. else
  373. {
  374. dwError = ERROR_WINHTTP_OPERATION_CANCELLED;
  375. }
  376. DEBUG_LEAVE (dwError);
  377. return dwError;
  378. }
  379. BOOL
  380. ICSocket::MatchOverlappedSemantics(
  381. IN DWORD dwSocketFlags
  382. )
  383. {
  384. DEBUG_ENTER((DBG_SOCKETS,
  385. Bool,
  386. "ICSocket::MatchOverlappedSemantics",
  387. "{%#x [%#x]} socketflags=%#x, desiredflags=%#x, completionport=%d",
  388. this,
  389. m_Socket,
  390. m_dwFlags,
  391. dwSocketFlags,
  392. g_hCompletionPort
  393. ));
  394. BOOL bRet = TRUE;
  395. if (((dwSocketFlags^m_dwFlags) & SF_OVERLAPPED)
  396. && (dwSocketFlags & SF_OVERLAPPED))
  397. {
  398. DWORD error;
  399. if (g_hCompletionPort
  400. && ((error = AssociateWithCompletionPort()) == ERROR_SUCCESS))
  401. {
  402. bRet = TRUE;
  403. }
  404. else
  405. {
  406. bRet = FALSE;
  407. //informational INET_ASSERT (FALSE);
  408. }
  409. }
  410. DEBUG_LEAVE (bRet);
  411. return bRet;
  412. }
  413. DWORD
  414. ICSocket::SocketConnect(
  415. IN LONG Timeout,
  416. IN INT Retries,
  417. IN DWORD dwFlags,
  418. IN CServerInfo *pServerInfo
  419. )
  420. /*++
  421. Routine Description:
  422. Initiate connection with server
  423. Arguments:
  424. Timeout - maximum amount of time (mSec) to wait for connection
  425. Retries - maximum number of attempts to connect
  426. dwFlags - flags controlling request
  427. pServerInfo - Server Info to connect with
  428. Return Value:
  429. DWORD
  430. Success - ERROR_SUCCESS
  431. ERROR_IO_PENDING
  432. Operation will complete asynchronously
  433. Failure - ERROR_NOT_ENOUGH_MEMORY
  434. Couldn't create FSM
  435. --*/
  436. {
  437. DEBUG_ENTER((DBG_SOCKETS,
  438. Dword,
  439. "ICSocket::SocketConnect",
  440. "{%#x [%#x]} %d, %d, %#x, %x",
  441. this,
  442. m_Socket,
  443. Timeout,
  444. Retries,
  445. dwFlags,
  446. pServerInfo
  447. ));
  448. DWORD error;
  449. CFsm_SocketConnect * pFsm;
  450. pFsm = New CFsm_SocketConnect(Timeout, Retries, dwFlags, this);
  451. if ( pFsm )
  452. {
  453. pFsm->SetServerInfo(pServerInfo);
  454. }
  455. error = DoFsm(pFsm);
  456. DEBUG_LEAVE(error);
  457. return error;
  458. }
  459. DWORD
  460. ICSocket::Connect(
  461. IN LONG Timeout,
  462. IN INT Retries,
  463. IN DWORD dwFlags
  464. )
  465. /*++
  466. Routine Description:
  467. Initiate connection with server
  468. Arguments:
  469. Timeout - maximum amount of time (mSec) to wait for connection
  470. Retries - maximum number of attempts to connect
  471. dwFlags - flags controlling request
  472. Return Value:
  473. DWORD
  474. Success - ERROR_SUCCESS
  475. ERROR_IO_PENDING
  476. Operation will complete asynchronously
  477. Failure - ERROR_NOT_ENOUGH_MEMORY
  478. Couldn't create FSM
  479. --*/
  480. {
  481. DEBUG_ENTER((DBG_SOCKETS,
  482. Dword,
  483. "ICSocket::Connect",
  484. "{%#x [%#x]} %d, %d, %#x",
  485. this,
  486. m_Socket,
  487. Timeout,
  488. Retries,
  489. dwFlags
  490. ));
  491. #ifdef TEST_CODE
  492. Timeout *= 20;
  493. Retries *= 20;
  494. #endif
  495. DWORD error;
  496. error = DoFsm(New CFsm_SocketConnect(Timeout, Retries, dwFlags, this));
  497. DEBUG_LEAVE(error);
  498. return error;
  499. }
  500. DWORD
  501. CFsm_SocketConnect::RunSM(
  502. IN CFsm * Fsm
  503. )
  504. /*++
  505. Routine Description:
  506. Runs next CFsm_SocketConnect state
  507. Arguments:
  508. Fsm - FSM controlling operation
  509. Return Value:
  510. DWORD
  511. Success - ERROR_SUCCESS
  512. Failure -
  513. --*/
  514. {
  515. DEBUG_ENTER((DBG_SOCKETS,
  516. Dword,
  517. "CFsm_SocketConnect::RunSM",
  518. "%#x",
  519. Fsm
  520. ));
  521. ICSocket * pSocket = (ICSocket *)Fsm->GetContext();
  522. CFsm_SocketConnect * stateMachine = (CFsm_SocketConnect *)Fsm;
  523. DWORD error;
  524. switch (Fsm->GetState()) {
  525. case FSM_STATE_INIT:
  526. error = pSocket->Connect_Start(stateMachine);
  527. break;
  528. case FSM_STATE_CONTINUE:
  529. error = pSocket->Connect_Continue(stateMachine);
  530. break;
  531. case FSM_STATE_ERROR:
  532. error = pSocket->Connect_Error(stateMachine);
  533. break;
  534. default:
  535. error = ERROR_WINHTTP_INTERNAL_ERROR;
  536. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  537. INET_ASSERT(FALSE);
  538. break;
  539. }
  540. DEBUG_LEAVE(error);
  541. return error;
  542. }
  543. DWORD
  544. ICSocket::Connect_Start(
  545. IN CFsm_SocketConnect * Fsm
  546. )
  547. /*++
  548. Routine Description:
  549. Starts a socket connect operation - creates a socket and connects it to a
  550. server using the address information returned by GetServiceAddress(). There
  551. may be several addresses to try. We return as soon as we successfully
  552. generate a connection, or after we have tried <Retries> attempts, or until
  553. <Timeout> milliseconds have elapsed
  554. Arguments:
  555. Fsm - socket connect FSM
  556. Return Value:
  557. DWORD
  558. Success - ERROR_SUCCESS
  559. ERROR_IO_PENDING
  560. Operation will complete asynchronously
  561. Failure -
  562. --*/
  563. {
  564. DEBUG_ENTER((DBG_SOCKETS,
  565. Dword,
  566. "ICSocket::Connect_Start",
  567. "{%#x [%#x]}, %#x(%d, %d, %#x)",
  568. this,
  569. m_Socket,
  570. Fsm,
  571. Fsm->m_Timeout,
  572. Fsm->m_Retries,
  573. Fsm->m_dwFlags
  574. ));
  575. PERF_ENTER(Connect_Start);
  576. CFsm_SocketConnect & fsm = *Fsm;
  577. //informational INET_ASSERT(lpThreadInfo != NULL);
  578. DWORD error = ERROR_SUCCESS;
  579. int serr = SOCKET_ERROR;
  580. BOOL fSynchronous = FALSE;
  581. INET_ASSERT(IsClosed());
  582. //
  583. // ensure the next state is CONTINUE. It may be INIT because we could have
  584. // been looping through bad addresses (if sufficient timeout & retries)
  585. //
  586. fsm.SetNextState(FSM_STATE_CONTINUE);
  587. //
  588. // get address to use. If exhausted, re-resolve
  589. //
  590. if (fsm.GetFunctionState() == FSM_STATE_2)
  591. {
  592. fsm.SetFunctionState(FSM_STATE_1);
  593. error = fsm.GetError();
  594. goto resolve_continue;
  595. }
  596. if (!fsm.m_pServerInfo->GetNextAddress(&fsm.m_dwResolutionId,
  597. &fsm.m_dwAddressIndex,
  598. GetPort(),
  599. fsm.m_pAddress
  600. )) {
  601. if (fsm.m_bResolved) {
  602. error = ERROR_WINHTTP_CANNOT_CONNECT;
  603. } else {
  604. fsm.SetFunctionState(FSM_STATE_2);
  605. fsm.SetNextState(FSM_STATE_INIT);
  606. fsm.m_dwAddressIndex = (DWORD)-1;
  607. error = fsm.m_pServerInfo->ResolveHost(&fsm.m_dwResolutionId,
  608. fsm.m_dwFlags
  609. );
  610. if (error == ERROR_IO_PENDING) {
  611. goto quit;
  612. }
  613. resolve_continue:
  614. fsm.m_bResolved = TRUE;
  615. if (error == ERROR_SUCCESS) {
  616. if (!fsm.m_pServerInfo->GetNextAddress(&fsm.m_dwResolutionId,
  617. &fsm.m_dwAddressIndex,
  618. GetPort(),
  619. fsm.m_pAddress
  620. )) {
  621. error = ERROR_WINHTTP_CANNOT_CONNECT;
  622. }
  623. }
  624. else if (error == ERROR_WINHTTP_NAME_NOT_RESOLVED)
  625. {
  626. fsm.SetNextState(FSM_STATE_CONTINUE);
  627. goto quit; // exit out NOW with ERROR_WINHTTP_NAME_NOT_RESOLVED, instead of CANNOT_CONNECT
  628. }
  629. }
  630. }
  631. if (error != ERROR_SUCCESS) {
  632. //
  633. // name resolution failed - done
  634. //
  635. goto quit;
  636. }
  637. //
  638. // update port for keep-alive info
  639. //
  640. // The port number field is in the same location in both a
  641. // sockaddr_in and a sockaddr_in6, so it is safe to cast the
  642. // sockaddr to sockaddr_in here - this works for IPv4 or IPv6.
  643. //
  644. INET_ASSERT(offsetof(SOCKADDR_IN, sin_port) == offsetof(SOCKADDR_IN6, sin6_port));
  645. SetPort(_I_ntohs(((LPSOCKADDR_IN)fsm.m_pAddress->RemoteAddr.lpSockaddr)->sin_port));
  646. //
  647. // BUGBUG - this code was supplying AF_UNSPEC to socket(), which should
  648. // be okay, but because of a bug in the Win95 wsipx driver
  649. // which manifests itself when we call bind(), we must send in
  650. // the address family supplied in the local socket address by
  651. // GetAddressByName()
  652. //
  653. int protocol;
  654. protocol = fsm.m_pAddress->iProtocol;
  655. m_Socket = _I_socket(fsm.m_pAddress->LocalAddr.lpSockaddr->sa_family,
  656. fsm.m_pAddress->iSocketType,
  657. protocol
  658. );
  659. if (m_Socket == INVALID_SOCKET) {
  660. DEBUG_PRINT(SOCKETS,
  661. ERROR,
  662. ("failed to create socket\n"
  663. ));
  664. goto check_socket_error;
  665. }
  666. DEBUG_PRINT(SOCKETS,
  667. INFO,
  668. ("created socket %#x\n",
  669. m_Socket
  670. ));
  671. //
  672. // inform the app that we are connecting to the server (but only on the
  673. // first attempt)
  674. //
  675. //if ((fsm.m_dwFlags & SF_INDICATE) && (error == ERROR_SUCCESS)) {
  676. if (fsm.m_dwFlags & SF_INDICATE) {
  677. error = InternetIndicateStatusAddress(WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER,
  678. fsm.m_pAddress->RemoteAddr.lpSockaddr,
  679. fsm.m_pAddress->RemoteAddr.iSockaddrLength
  680. );
  681. if (error != ERROR_SUCCESS)
  682. {
  683. INET_ASSERT(error == ERROR_WINHTTP_OPERATION_CANCELLED);
  684. fsm.SetNextState(FSM_STATE_DONE);
  685. goto quit;
  686. }
  687. }
  688. //
  689. // if requested to, put the socket in non-blocking mode
  690. //
  691. if (fsm.m_dwFlags & SF_NON_BLOCKING
  692. && (GlobalRunningNovellClient32 ? GlobalNonBlockingClient32 : TRUE)) {
  693. error = SetNonBlockingMode(TRUE);
  694. if (error != ERROR_SUCCESS) {
  695. fsm.SetErrorState(error);
  696. goto quit;
  697. }
  698. }
  699. //
  700. // bind the socket to the local address
  701. //
  702. DEBUG_PRINT(SOCKETS,
  703. INFO,
  704. ("binding to local address %A, port %d, index %d\n",
  705. fsm.m_pAddress->LocalAddr.lpSockaddr,
  706. _I_ntohs(((LPSOCKADDR_IN)fsm.m_pAddress->LocalAddr.lpSockaddr)->sin_port),
  707. fsm.m_dwAddressIndex
  708. ));
  709. serr = _I_bind(m_Socket,
  710. fsm.m_pAddress->LocalAddr.lpSockaddr,
  711. fsm.m_pAddress->LocalAddr.iSockaddrLength
  712. );
  713. if (serr == SOCKET_ERROR) {
  714. DEBUG_PRINT(SOCKETS,
  715. ERROR,
  716. ("failed to bind socket %#x\n",
  717. m_Socket
  718. ));
  719. goto check_socket_error;
  720. }
  721. //
  722. // record source port (useful for matching with net sniff)
  723. //
  724. SetSourcePort();
  725. DEBUG_PRINT(SOCKETS,
  726. INFO,
  727. ("socket %#x bound to port %d (%#x)\n",
  728. m_Socket,
  729. m_SourcePort,
  730. m_SourcePort
  731. ));
  732. //
  733. // let another thread know the socket to cancel if it wants to kill
  734. // this operation
  735. //
  736. INET_ASSERT(fsm.GetMappedHandleObject() != NULL);
  737. if (fsm.GetMappedHandleObject() != NULL) {
  738. fsm.GetMappedHandleObject()->SetAbortHandle(this);
  739. }
  740. //
  741. // try to connect to the next address
  742. //
  743. DEBUG_PRINT(SOCKETS,
  744. INFO,
  745. ("connecting %#x/%d to remote address %A, port %d, index %d\n",
  746. m_Socket,
  747. m_SourcePort,
  748. fsm.m_pAddress->RemoteAddr.lpSockaddr,
  749. _I_ntohs(((LPSOCKADDR_IN)fsm.m_pAddress->RemoteAddr.lpSockaddr)->sin_port),
  750. fsm.m_dwAddressIndex
  751. ));
  752. #if 0
  753. #define SIN4 ((LPSOCKADDR_IN)fsm.m_pAddress->RemoteAddr.lpSockaddr)
  754. #define SIN6 ((LPSOCKADDR_IN6)fsm.m_pAddress->RemoteAddr.lpSockaddr)
  755. if (SIN4->sin_family == AF_INET) {
  756. DEBUG_PRINT(SOCKETS, INFO, (" sin_family = AF_INET\n"));
  757. DEBUG_PRINT(SOCKETS, INFO, (" sin_port = %u\n", _I_ntohs(SIN4->sin_port)));
  758. DEBUG_PRINT(SOCKETS, INFO, (" sin_addr.S_un.S_addr = 0x%x\n", SIN4->sin_addr.S_un.S_addr));
  759. DEBUG_PRINT(SOCKETS, INFO, (" sin_addr = %d.%d.%d.%d\n",
  760. SIN4->sin_addr.S_un.S_un_b.s_b1,
  761. SIN4->sin_addr.S_un.S_un_b.s_b2,
  762. SIN4->sin_addr.S_un.S_un_b.s_b3,
  763. SIN4->sin_addr.S_un.S_un_b.s_b4));
  764. } else {
  765. DEBUG_PRINT(SOCKETS, INFO, (" sin_family = AF_INET6\n"));
  766. DEBUG_PRINT(SOCKETS, INFO, (" sin6_port = %u\n", _I_ntohs(SIN6->sin6_port)));
  767. DEBUG_PRINT(SOCKETS, INFO, (" sin6_flowinfo = %u\n", SIN6->sin6_flowinfo));
  768. DEBUG_PRINT(SOCKETS, INFO, (" sin6_addr = %.04x:%.04x:%.04x:%.04x:%.04x:%.04x:%.04x:%.04x\n",
  769. _I_ntohs(SIN6->sin6_addr.s6_words[0]),
  770. _I_ntohs(SIN6->sin6_addr.s6_words[1]),
  771. _I_ntohs(SIN6->sin6_addr.s6_words[2]),
  772. _I_ntohs(SIN6->sin6_addr.s6_words[3]),
  773. _I_ntohs(SIN6->sin6_addr.s6_words[4]),
  774. _I_ntohs(SIN6->sin6_addr.s6_words[5]),
  775. _I_ntohs(SIN6->sin6_addr.s6_words[6]),
  776. _I_ntohs(SIN6->sin6_addr.s6_words[7])));
  777. DEBUG_PRINT(SOCKETS, INFO, (" ai_addr->sin6_scope_id = %u\n", SIN6->sin6_scope_id));
  778. }
  779. #endif
  780. fsm.SetNextState(FSM_STATE_CONTINUE);
  781. fsm.StartTimer();
  782. #ifdef TEST_CODE
  783. SetLastError(-1);
  784. serr = -1;
  785. #else
  786. //if we are running in blocking mode (ie synchronous case) w/ timeout, unblock for
  787. //the connect so we can enforce the timeout.
  788. if (!(fsm.m_dwFlags & SF_NON_BLOCKING)
  789. && (fsm.GetTimeout() != INFINITE))
  790. {
  791. fSynchronous = TRUE;
  792. error = SetNonBlockingMode(TRUE);
  793. if (error != ERROR_SUCCESS)
  794. {
  795. fsm.SetErrorState(error);
  796. goto quit;
  797. }
  798. }
  799. if (IsSocks()) {
  800. serr = SocksConnect((LPSOCKADDR_IN)fsm.m_pAddress->RemoteAddr.lpSockaddr,
  801. fsm.m_pAddress->RemoteAddr.iSockaddrLength
  802. );
  803. } else {
  804. serr = _I_connect(m_Socket,
  805. fsm.m_pAddress->RemoteAddr.lpSockaddr,
  806. fsm.m_pAddress->RemoteAddr.iSockaddrLength
  807. );
  808. }
  809. #endif
  810. //
  811. // here if a socket operation failed, in which case serr will be SOCKET_ERROR
  812. //
  813. check_socket_error:
  814. if (serr == 0) {
  815. //
  816. // successful (probably synchronous) connect completion
  817. //
  818. //
  819. // in the sync case, we just call the continue handler. No need to
  820. // return to the state handler
  821. //
  822. if (fSynchronous) // we must have marked the socket non-blocking ealier
  823. {
  824. DWORD dwError;
  825. if ((dwError = SetNonBlockingMode(FALSE)) != ERROR_SUCCESS)
  826. {
  827. error = MapInternetError(dwError);
  828. fsm.SetErrorState(error);
  829. goto quit; // no connect re-try if we failed to restore the socket mode
  830. }
  831. }
  832. Connect_Continue(Fsm);
  833. goto quit;
  834. }
  835. //
  836. // here if a socket operation failed. We have to read the socket error in
  837. // this thread before doing anything else or we'll lose the error. We handle
  838. // it in Connect_Error()
  839. //
  840. error = _I_WSAGetLastError();
  841. DEBUG_PRINT(SOCKETS,
  842. INFO,
  843. ("connect(%#x) returns %d\n",
  844. m_Socket,
  845. error
  846. ));
  847. if (fSynchronous && (error == WSAEWOULDBLOCK))
  848. {
  849. int n = 1;
  850. struct fd_set write_fds;
  851. struct fd_set except_fds;
  852. FD_ZERO(&write_fds);
  853. FD_ZERO(&except_fds);
  854. SOCKET sock = m_Socket;
  855. // connect() & send()
  856. DEBUG_PRINT(ASYNC,
  857. INFO,
  858. ("%s FSM %#x WRITE waiting on socket %#x\n",
  859. fsm.MapType(),
  860. &fsm,
  861. sock
  862. ));
  863. FD_SET(sock, &write_fds);
  864. // all sockets are checked for exception
  865. FD_SET(sock, &except_fds);
  866. LONG timeout = fsm.GetTimeout();
  867. struct timeval to = {0,0};
  868. struct timeval* pto;
  869. if (timeout != INFINITE)
  870. {
  871. to.tv_sec = timeout / 1000;
  872. to.tv_usec = (timeout % 1000) * 1000;
  873. pto = &to;
  874. }
  875. else
  876. {
  877. pto = NULL;
  878. }
  879. DEBUG_PRINT(ASYNC,
  880. INFO,
  881. ("waiting %d mSec (%d.%06d) for select(). %d sockets\n",
  882. timeout,
  883. pto ? to.tv_sec : -1,
  884. pto ? to.tv_usec : -1,
  885. n
  886. ));
  887. n = PERF_Select(n, NULL, &write_fds, &except_fds, pto);
  888. DEBUG_PRINT(ASYNC,
  889. INFO,
  890. ("select() returns %d\n",
  891. n
  892. ));
  893. error = ERROR_WINHTTP_CANNOT_CONNECT;
  894. if (n == 0)
  895. {
  896. INET_ASSERT (pto != NULL);
  897. error = ERROR_WINHTTP_TIMEOUT;
  898. }
  899. else if (n > 0)
  900. {
  901. if (FD_ISSET(sock, &except_fds))
  902. {
  903. DEBUG_PRINT(ASYNC,
  904. INFO,
  905. ("%s FSM %#x socket %#x exception\n",
  906. fsm.MapType(),
  907. fsm,
  908. sock
  909. ));
  910. }
  911. else if (FD_ISSET(sock, &write_fds))
  912. {
  913. DEBUG_PRINT(ASYNC,
  914. INFO,
  915. ("%s FSM %#x socket %#x completed\n",
  916. fsm.MapType(),
  917. fsm,
  918. sock
  919. ));
  920. error = ERROR_SUCCESS;
  921. }
  922. else
  923. {
  924. INET_ASSERT (FALSE);
  925. }
  926. } //n >= 0
  927. else
  928. {
  929. error = MapInternetError(_I_WSAGetLastError());
  930. }
  931. //Now set the socket back to blocking mode.
  932. // If we run into an error doing that, then fall out of the connect loop
  933. // Else we'll fall into the Connect_Continue->Connect_Error codepath, which
  934. // will also account for count-outs and timeouts.
  935. DWORD dwError;
  936. if ((dwError = SetNonBlockingMode(FALSE)) != ERROR_SUCCESS)
  937. {
  938. error = MapInternetError(dwError);
  939. fsm.SetErrorState(error);
  940. goto quit;
  941. }
  942. } //fSynchronous
  943. //
  944. // if we are using non-blocking sockets then we need to wait until the
  945. // connect has completed, or an error occurs.
  946. // If we got any status other than WSAEWOULDBLOCK then we have to handle
  947. // the error
  948. //
  949. if (IsNonBlocking() && (error == WSAEWOULDBLOCK)) {
  950. DEBUG_PRINT(SOCKETS,
  951. INFO,
  952. ("connect() blocked, socket %#x, port %d\n",
  953. m_Socket,
  954. m_SourcePort
  955. ));
  956. fsm.SetAction(FSM_ACTION_CONNECT);
  957. DWORD timeout = GetTimeoutValue(WINHTTP_OPTION_CONNECT_TIMEOUT);
  958. #ifndef WININET_SERVER_CORE //no cache
  959. if (pObject != NULL) {
  960. if (pObject->IsFromCacheTimeoutSet()
  961. && (pObject->GetObjectType() == TypeHttpRequestHandle)
  962. && ((HTTP_REQUEST_HANDLE_OBJECT *)pObject)->CanRetrieveFromCache()) {
  963. timeout = GetTimeoutValue(WINHTTP_OPTION_FROM_CACHE_TIMEOUT);
  964. DWORD connectTime = fsm.m_pServerInfo->GetConnectTime();
  965. if (connectTime == 0) {
  966. connectTime = timeout;
  967. }
  968. timeout += connectTime;
  969. }
  970. }
  971. #endif //no cache
  972. fsm.SetTimeout(timeout);
  973. fsm.SetNextState(FSM_STATE_CONTINUE);
  974. //
  975. // after we set the state to waiting, and get ERROR_IO_PENDING from
  976. // QueueSocketWorkItem() then we can no longer touch this FSM until
  977. // it completes asynchronously
  978. //
  979. //
  980. // perf - test the socket. If this completes quickly we don't take a
  981. // context switch
  982. //
  983. //error = WaitForReceive(0);
  984. //if (error == ERROR_WINHTTP_TIMEOUT) {
  985. error = QueueSocketWorkItem(Fsm, m_Socket);
  986. //}
  987. if (error == ERROR_SUCCESS) {
  988. //
  989. // in the unlikely event the request completed quickly and
  990. // successfully
  991. //
  992. serr = 0;
  993. goto check_socket_error;
  994. } else if (error == ERROR_IO_PENDING) {
  995. //
  996. // the request is pending. We already set waiting state
  997. //
  998. goto quit;
  999. }
  1000. //
  1001. // if here then QueueSocketWorkItem() returned some other error
  1002. //
  1003. }
  1004. else
  1005. {
  1006. //
  1007. // some other socket error occurred. Convert to INTERNET error
  1008. //
  1009. //
  1010. // Also okay to be here for successful synchronous connect with timeout.
  1011. //
  1012. if (error)
  1013. fsm.SetErrorState(MapInternetError(error));
  1014. error = Connect_Continue(Fsm);
  1015. }
  1016. if (error)
  1017. fsm.SetErrorState(error);
  1018. quit:
  1019. //
  1020. // we are done if not pending AND we will not re-enter this state in order
  1021. // to re-do the name resolution/find another address
  1022. //
  1023. if ((error != ERROR_IO_PENDING) && (fsm.GetNextState() != FSM_STATE_INIT))
  1024. {
  1025. fsm.SetDone();
  1026. PERF_LEAVE(Connect_Start);
  1027. }
  1028. DEBUG_LEAVE(error);
  1029. return error;
  1030. }
  1031. DWORD
  1032. ICSocket::Connect_Continue(
  1033. IN CFsm_SocketConnect * Fsm
  1034. )
  1035. /*++
  1036. Routine Description:
  1037. Performs common processing after connect completion or failure
  1038. Arguments:
  1039. Fsm - reference to socket connect finite state machine
  1040. Return Value:
  1041. DWORD
  1042. Success - ERROR_SUCCESS
  1043. ERROR_IO_PENDING
  1044. Operation will complete asynchronously
  1045. Failure -
  1046. --*/
  1047. {
  1048. DEBUG_ENTER((DBG_SOCKETS,
  1049. Dword,
  1050. "ICSocket::Connect_Continue",
  1051. "{%#x [%#x/%d]}, %#x(%d, %d, %#x)",
  1052. this,
  1053. GetSocket(),
  1054. GetSourcePort(),
  1055. Fsm,
  1056. Fsm->m_Timeout,
  1057. Fsm->m_Retries,
  1058. Fsm->m_dwFlags
  1059. ));
  1060. PERF_ENTER(Connect_Continue);
  1061. CFsm_SocketConnect & fsm = *Fsm;
  1062. fsm.StopTimer();
  1063. // INET_ASSERT((fsm.GetMappedHandleObject() != NULL)
  1064. // ? (fsm.GetMappedHandleObject()->GetAbortHandle() != NULL)
  1065. // : TRUE);
  1066. DWORD error = fsm.GetError();
  1067. //INET_ASSERT(error != SOCKET_ERROR);
  1068. DEBUG_PRINT(SOCKETS,
  1069. INFO,
  1070. ("connect() resumed, socket %#x, port %d\n",
  1071. m_Socket,
  1072. m_SourcePort
  1073. ));
  1074. //
  1075. // check for aborted request
  1076. //
  1077. if (IsAborted())
  1078. {
  1079. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1080. }
  1081. if (error == ERROR_SUCCESS)
  1082. {
  1083. //
  1084. // Socket successfully created and bound and connected - now, if async,
  1085. // associate IOCP with this socket.
  1086. //
  1087. if (fsm.m_dwFlags & SF_NON_BLOCKING)
  1088. {
  1089. DEBUG_PRINT(SOCKETS,
  1090. INFO,
  1091. ("***CreateIoCompletionPort: (m_Socket)%#x, (hcomp)%#x, (icsocket-compkey)%#x, %#x, (app handle)%#x, (fsm)%#x, (mapped handle obj)%#x",
  1092. m_Socket,
  1093. g_hCompletionPort,
  1094. this,
  1095. 0,
  1096. fsm.GetAppHandle(),
  1097. fsm,
  1098. fsm.GetMappedHandleObject()
  1099. ));
  1100. if ((error = AssociateWithCompletionPort()) != ERROR_SUCCESS)
  1101. {
  1102. fsm.SetErrorState(error);
  1103. }
  1104. }
  1105. }
  1106. if (error == ERROR_SUCCESS) {
  1107. DEBUG_PRINT(SOCKETS,
  1108. INFO,
  1109. ("socket %#x/port %d connected; time = %d mSec\n",
  1110. m_Socket,
  1111. m_SourcePort,
  1112. fsm.ReadTimer()
  1113. ));
  1114. error = Connect_Finish(Fsm);
  1115. }
  1116. if (error != ERROR_SUCCESS) {
  1117. DEBUG_PRINT(SOCKETS,
  1118. ERROR,
  1119. ("failed to connect socket %#x/port %d: error %s\n",
  1120. m_Socket,
  1121. m_SourcePort,
  1122. InternetMapError(error)
  1123. ));
  1124. fsm.SetError(error);
  1125. error = Connect_Error(Fsm);
  1126. }
  1127. PERF_LEAVE(Connect_Continue);
  1128. DEBUG_LEAVE(error);
  1129. return error;
  1130. }
  1131. DWORD
  1132. ICSocket::Connect_Error(
  1133. IN CFsm_SocketConnect * Fsm
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. Called to handle a connect error. Either causes the FSM to terminate or
  1138. prepares the FSM to try another connection
  1139. Arguments:
  1140. Fsm - socket connect FSM
  1141. Return Value:
  1142. DWORD
  1143. Success - ERROR_SUCCESS
  1144. Failure -
  1145. --*/
  1146. {
  1147. DEBUG_ENTER((DBG_SOCKETS,
  1148. Dword,
  1149. "ICSocket::Connect_Error",
  1150. "{%#x [%#x/%d]}, %#x(%d, %d, %#x)",
  1151. this,
  1152. GetSocket(),
  1153. GetSourcePort(),
  1154. Fsm,
  1155. Fsm->m_Timeout,
  1156. Fsm->m_Retries,
  1157. Fsm->m_dwFlags
  1158. ));
  1159. PERF_ENTER(Connect_Error);
  1160. CFsm_SocketConnect & fsm = *Fsm;
  1161. fsm.StopTimer();
  1162. INTERNET_HANDLE_OBJECT * pObject = fsm.GetMappedHandleObject();
  1163. //
  1164. // no longer performing socket operation - clear abort handle
  1165. //
  1166. INET_ASSERT(pObject != NULL);
  1167. if (pObject != NULL) {
  1168. pObject->ResetAbortHandle();
  1169. }
  1170. DWORD error = fsm.GetError();
  1171. BOOL bRestartable = FALSE;
  1172. //INET_ASSERT(error != SOCKET_ERROR);
  1173. INET_ASSERT(error != ERROR_SUCCESS);
  1174. //
  1175. // check for aborted request - this overrides any socket error
  1176. //
  1177. if (IsAborted() || error == ERROR_WINHTTP_OPERATION_CANCELLED)
  1178. {
  1179. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1180. }
  1181. else if (fsm.IsCountedOut()
  1182. || fsm.IsTimedOut() // entire request timeout
  1183. || (error == ERROR_WINHTTP_TIMEOUT))
  1184. { // just this request t/o
  1185. DEBUG_PRINT(SOCKETS,
  1186. INFO,
  1187. ("counted out or timed out\n"
  1188. ));
  1189. // VENKATK_BUG verify this:
  1190. // CANNOT_CONNECT takes precedence over TIMEOUT
  1191. //
  1192. if (fsm.IsTimedOut())
  1193. {
  1194. error = ERROR_WINHTTP_TIMEOUT;
  1195. }
  1196. else if (fsm.IsCountedOut())
  1197. {
  1198. error = ERROR_WINHTTP_CANNOT_CONNECT;
  1199. }
  1200. }
  1201. else if (error != ERROR_NOT_ENOUGH_MEMORY)
  1202. {
  1203. //
  1204. // not aborted, timed-out, counted-out, or offline. We can try again
  1205. //
  1206. bRestartable = TRUE;
  1207. }
  1208. //
  1209. // if the socket is open, close it and try the next connection. Invalidate
  1210. // the address we tried
  1211. //
  1212. if (IsOpen())
  1213. {
  1214. Close();
  1215. }
  1216. DWORD mappedError = fsm.GetMappedError();
  1217. DEBUG_PRINT(SOCKETS,
  1218. INFO,
  1219. ("mapped error = %d [%s]\n",
  1220. mappedError,
  1221. InternetMapError(mappedError)
  1222. ));
  1223. //
  1224. // don't invalidate address if from-cache-if-net-fail timeout
  1225. //
  1226. BOOL bInvalidate = TRUE;
  1227. if ((pObject != NULL) && pObject->IsFromCacheTimeoutSet())
  1228. {
  1229. bInvalidate = FALSE;
  1230. }
  1231. if ((mappedError == WSAENETUNREACH)
  1232. || (mappedError == WSAETIMEDOUT)
  1233. || ((error == ERROR_WINHTTP_TIMEOUT) && bInvalidate)
  1234. || (error == ERROR_WINHTTP_CANNOT_CONNECT)
  1235. #ifdef TEST_CODE
  1236. || (error == (DWORD)-1)
  1237. #endif
  1238. )
  1239. {
  1240. fsm.m_pServerInfo->InvalidateAddress(fsm.m_dwResolutionId,
  1241. fsm.m_dwAddressIndex
  1242. );
  1243. }
  1244. //
  1245. // if the operation was cancelled or we lost connectivity then quit
  1246. //
  1247. if (bRestartable)
  1248. {
  1249. fsm.SetNextState(FSM_STATE_INIT);
  1250. //bug 37206
  1251. fsm.SetError(ERROR_SUCCESS);
  1252. error = ERROR_SUCCESS;
  1253. }
  1254. else
  1255. {
  1256. fsm.SetDone(error);
  1257. PERF_LEAVE(Connect_Error);
  1258. }
  1259. DEBUG_LEAVE(error);
  1260. return error;
  1261. }
  1262. DWORD
  1263. ICSocket::Connect_Finish(
  1264. IN CFsm_SocketConnect * Fsm
  1265. )
  1266. /*++
  1267. Routine Description:
  1268. Called when the connection has been successfully established
  1269. Arguments:
  1270. Fsm - socket connect FSM
  1271. Return Value:
  1272. DWORD
  1273. Success - ERROR_SUCCESS
  1274. Failure -
  1275. --*/
  1276. {
  1277. DEBUG_ENTER((DBG_SOCKETS,
  1278. Dword,
  1279. "ICSocket::Connect_Finish",
  1280. "{%#x [%#x/%d]}, %#x(%d, %d, %#x)",
  1281. this,
  1282. GetSocket(),
  1283. GetSourcePort(),
  1284. Fsm,
  1285. Fsm->m_Timeout,
  1286. Fsm->m_Retries,
  1287. Fsm->m_dwFlags
  1288. ));
  1289. PERF_ENTER(Connect_Finish);
  1290. CFsm_SocketConnect & fsm = *Fsm;
  1291. // INET_ASSERT(IsOpen());
  1292. if (IsAborted())
  1293. {
  1294. return ERROR_WINHTTP_OPERATION_CANCELLED;
  1295. }
  1296. //
  1297. // store the average connect time to this server in our CServerInfo
  1298. //
  1299. if (fsm.m_pServerInfo != NULL) {
  1300. fsm.m_pServerInfo->UpdateConnectTime(fsm.ReadTimer());
  1301. }
  1302. if (fsm.m_pOriginServer != NULL) {
  1303. fsm.m_pOriginServer->UpdateConnectTime(fsm.ReadTimer());
  1304. }
  1305. #ifdef TEST_CODE
  1306. BOOL optval;
  1307. int optlen = sizeof(optval);
  1308. int serr = _I_getsockopt(GetSocket(),
  1309. IPPROTO_TCP,
  1310. TCP_NODELAY,
  1311. (char FAR *)&optval,
  1312. &optlen
  1313. );
  1314. if (serr != 0) {
  1315. DEBUG_PRINT(SOCKETS,
  1316. ERROR,
  1317. ("getsockopt(TCP_NODELAY) returns %s (%d)\n",
  1318. InternetMapError(_I_WSAGetLastError()),
  1319. _I_WSAGetLastError()
  1320. ));
  1321. }
  1322. #endif
  1323. //
  1324. // no longer performing socket operation - clear abort handle
  1325. //
  1326. INET_ASSERT(fsm.GetMappedHandleObject() != NULL);
  1327. if (fsm.GetMappedHandleObject() != NULL) {
  1328. fsm.GetMappedHandleObject()->ResetAbortHandle();
  1329. }
  1330. //
  1331. // set the send & receive buffer sizes if not -1 (meaning don't change)
  1332. //
  1333. DWORD bufferLength;
  1334. bufferLength = GetBufferLength(ReceiveBuffer);
  1335. if (bufferLength != (DWORD)-1) {
  1336. SetBufferLength(ReceiveBuffer, bufferLength);
  1337. }
  1338. bufferLength = GetBufferLength(SendBuffer);
  1339. if (bufferLength != (DWORD)-1) {
  1340. SetBufferLength(SendBuffer, bufferLength);
  1341. }
  1342. //
  1343. // disable send coalescing
  1344. //
  1345. SetSendCoalescing(FALSE);
  1346. //
  1347. // let the app know we connected to the server successfully
  1348. //
  1349. if (fsm.m_dwFlags & SF_INDICATE) {
  1350. InternetIndicateStatusAddress(WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER,
  1351. fsm.m_pAddress->RemoteAddr.lpSockaddr,
  1352. fsm.m_pAddress->RemoteAddr.iSockaddrLength
  1353. );
  1354. }
  1355. fsm.SetDone();
  1356. PERF_LEAVE(Connect_Finish);
  1357. DEBUG_LEAVE(ERROR_SUCCESS);
  1358. return ERROR_SUCCESS;
  1359. }
  1360. int
  1361. ICSocket::SocksConnect(
  1362. IN LPSOCKADDR_IN pSockaddr,
  1363. IN INT nLen
  1364. )
  1365. /*++
  1366. Routine Description:
  1367. Connect to remote host via SOCKS proxy. Modified from original. If we are
  1368. here then we are going specifically via a known SOCKS proxy. There is now
  1369. only one Hosts object, containing a single SOCKD socks proxy address and
  1370. user name
  1371. N.B. Irrespective of whether we are non-blocking, this function executes
  1372. in blocking mode (we expect that we are on an intranet and complete quickly)
  1373. Arguments:
  1374. pSockaddr - address of remote host (on other side of SOCKS firewall)
  1375. nLen - length of *pSockaddr
  1376. Return Value:
  1377. int
  1378. Success - 0
  1379. Failure - -1
  1380. --*/
  1381. {
  1382. UNREFERENCED_PARAMETER(nLen);
  1383. DEBUG_ENTER((DBG_SOCKETS,
  1384. Int,
  1385. "ICSocket::SocksConnect",
  1386. "{%#x} %#x, %d",
  1387. GetSocket(),
  1388. pSockaddr,
  1389. nLen
  1390. ));
  1391. //
  1392. // BUGBUG - should check if the socket type is SOCK_STREAM or if we have
  1393. // already connected this socket. This code was part of original
  1394. // general purpose solution. We don't need it
  1395. //
  1396. //
  1397. // initialize sockaddr for connecting to SOCKS firewall
  1398. //
  1399. struct sockaddr_in sin;
  1400. sin.sin_family = AF_INET;
  1401. sin.sin_port = _I_htons(m_SocksPort);
  1402. sin.sin_addr.s_addr = m_SocksAddress;
  1403. memset(&sin.sin_zero, 0, sizeof(sin.sin_zero));
  1404. //
  1405. // initialize SOCKS request packet
  1406. //
  1407. struct {
  1408. unsigned char VN;
  1409. unsigned char CD;
  1410. unsigned short DSTPORT;
  1411. unsigned long DSTIP;
  1412. char UserId[255];
  1413. } request;
  1414. request.VN = 4;
  1415. request.CD = 1;
  1416. request.DSTPORT = pSockaddr->sin_port;
  1417. request.DSTIP = pSockaddr->sin_addr.s_addr;
  1418. DWORD length = sizeof(request.UserId);
  1419. length += 8 + 1; // 8 == sizeof fixed portion of request;
  1420. // +1 for additional '\0'
  1421. //
  1422. // put socket into blocking mode
  1423. //
  1424. BOOL non_blocking = IsNonBlocking();
  1425. if (non_blocking) {
  1426. SetNonBlockingMode(FALSE);
  1427. }
  1428. //
  1429. // communicate with SOCKS firewall: send SOCKS request & receive response
  1430. //
  1431. int serr = _I_connect(m_Socket, (LPSOCKADDR)&sin, sizeof(sin));
  1432. if (serr != SOCKET_ERROR) {
  1433. serr = _I_send(m_Socket, (char *)&request, length, 0);
  1434. if (serr == (int)length) {
  1435. char response[256];
  1436. serr = _I_recv(m_Socket, (char *)response, sizeof(response), 0);
  1437. if( serr == 1 ) {
  1438. // need to read at least 2 bytes
  1439. DEBUG_PRINT(SOCKETS,
  1440. ERROR,
  1441. ("need to read one more byte\n"));
  1442. serr = _I_recv(
  1443. m_Socket, (char *)(&response[1]), sizeof(response) - 1, 0);
  1444. }
  1445. if (serr != SOCKET_ERROR) {
  1446. if (response[1] != 90) {
  1447. serr = SOCKET_ERROR;
  1448. }
  1449. } else {
  1450. DEBUG_PRINT(SOCKETS,
  1451. ERROR,
  1452. ("recv(%#x) returns %d\n",
  1453. m_Socket,
  1454. _I_WSAGetLastError()
  1455. ));
  1456. }
  1457. } else {
  1458. DEBUG_PRINT(SOCKETS,
  1459. ERROR,
  1460. ("send(%#x) returns %d\n",
  1461. m_Socket,
  1462. _I_WSAGetLastError()
  1463. ));
  1464. serr = SOCKET_ERROR;
  1465. }
  1466. } else {
  1467. DEBUG_PRINT(SOCKETS,
  1468. ERROR,
  1469. ("connect(%#x) returns %d\n",
  1470. m_Socket,
  1471. _I_WSAGetLastError()
  1472. ));
  1473. }
  1474. //
  1475. // if originally non-blocking, make socket non-blocking again
  1476. //
  1477. if (non_blocking) {
  1478. SetNonBlockingMode(TRUE);
  1479. }
  1480. //
  1481. // if success, mark the socket as being connected through firewall
  1482. //
  1483. if (serr == SOCKET_ERROR) {
  1484. _I_WSASetLastError(WSAECONNREFUSED);
  1485. }
  1486. DEBUG_LEAVE(serr);
  1487. return serr;
  1488. }
  1489. DWORD
  1490. ICSocket::Disconnect(
  1491. IN DWORD dwFlags
  1492. )
  1493. /*++
  1494. Routine Description:
  1495. Undoes the work of ConnectSocket - i.e. closes a connected socket. We make
  1496. callbacks to inform the app that this socket is being closed
  1497. Arguments:
  1498. dwFlags - controlling operation
  1499. Return Value:
  1500. DWORD
  1501. Success - ERROR_SUCCESS
  1502. Failure - WSA error
  1503. --*/
  1504. {
  1505. DEBUG_ENTER((DBG_SOCKETS,
  1506. Dword,
  1507. "ICSocket::Disconnect",
  1508. "{%#x/%d} %#x",
  1509. GetSocket(),
  1510. GetSourcePort(),
  1511. dwFlags
  1512. ));
  1513. //
  1514. // let the app know we are closing the connection
  1515. //
  1516. if (dwFlags & SF_INDICATE) {
  1517. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NULL, 0);
  1518. }
  1519. DWORD error = Close();
  1520. if ((error == ERROR_SUCCESS) && (dwFlags & SF_INDICATE)) {
  1521. //
  1522. // let the app know the connection is closed
  1523. //
  1524. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NULL, 0);
  1525. }
  1526. DEBUG_LEAVE(error);
  1527. return error;
  1528. }
  1529. DWORD
  1530. ICSocket::Close(
  1531. VOID
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. Closes a connected socket. Assumes that any linger or shutdown etc.
  1536. requirements have already been applied to the socket
  1537. Arguments:
  1538. none.
  1539. Return Value:
  1540. DWORD
  1541. Success - ERROR_SUCCESS
  1542. Failure - WSA error
  1543. --*/
  1544. {
  1545. DEBUG_ENTER((DBG_SOCKETS,
  1546. Dword,
  1547. "ICSocket::Close",
  1548. "{%#x/%d}",
  1549. GetSocket(),
  1550. GetSourcePort()
  1551. ));
  1552. DWORD error = ERROR_SUCCESS;
  1553. if (IsOpen()) {
  1554. //dprintf("**** closing %#x\n", m_Socket);
  1555. int serr;
  1556. SOCKET hSocket;
  1557. // remove socket handle from ICSocket before closesocket()
  1558. hSocket= m_Socket;
  1559. m_Socket = INVALID_SOCKET;
  1560. __try {
  1561. serr = _I_closesocket(hSocket);
  1562. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1563. serr = 0;
  1564. }
  1565. ENDEXCEPT
  1566. error = (serr == SOCKET_ERROR)
  1567. ? MapInternetError(_I_WSAGetLastError())
  1568. : ERROR_SUCCESS;
  1569. }
  1570. //
  1571. // the socket is now closed
  1572. //
  1573. DEBUG_LEAVE(error);
  1574. return error;
  1575. }
  1576. DWORD
  1577. ICSocket::Abort(
  1578. VOID
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. Aborts a socket by simply closing it
  1583. Arguments:
  1584. None.
  1585. Return Value:
  1586. DWORD
  1587. Success - ERROR_SUCCESS
  1588. Failure -
  1589. --*/
  1590. {
  1591. DEBUG_ENTER((DBG_SOCKETS,
  1592. Dword,
  1593. "ICSocket::Abort",
  1594. "{%#x/%d}",
  1595. GetSocket(),
  1596. GetSourcePort()
  1597. ));
  1598. // set aborted flag before close
  1599. SetAborted();
  1600. DWORD error = Close();
  1601. DEBUG_LEAVE(error);
  1602. return error;
  1603. }
  1604. DWORD
  1605. ICSocket::Shutdown(
  1606. IN DWORD dwControl
  1607. )
  1608. /*++
  1609. Routine Description:
  1610. Stops any more send/receives from the socket
  1611. Arguments:
  1612. dwControl - 0 to stop receives, 1 to stop sends, 2 to stop both
  1613. Return Value:
  1614. DWORD
  1615. Success - ERROR_SUCCESS
  1616. Failure - WSA error
  1617. --*/
  1618. {
  1619. DEBUG_ENTER((DBG_SOCKETS,
  1620. Dword,
  1621. "ICSocket::Shutdown",
  1622. "{%#x/%d}",
  1623. GetSocket(),
  1624. GetSourcePort()
  1625. ));
  1626. DWORD error = ERROR_SUCCESS;
  1627. if (IsOpen()) {
  1628. int serr = _I_shutdown(m_Socket, dwControl);
  1629. if (serr == SOCKET_ERROR) {
  1630. //
  1631. // map any sockets error to WinHttp error
  1632. //
  1633. error = MapInternetError(_I_WSAGetLastError());
  1634. }
  1635. }
  1636. DEBUG_LEAVE(error);
  1637. return error;
  1638. }
  1639. BOOL
  1640. ICSocket::IsReset(
  1641. VOID
  1642. )
  1643. /*++
  1644. Routine Description:
  1645. Determines if the socket has been closed. We peek the socket for 1 byte. If
  1646. the socket is in blocking mode, we temporarily switch to non-blocking to
  1647. perform the test - we don't want to block, nor remove any data from the
  1648. socket
  1649. Arguments:
  1650. None.
  1651. Return Value:
  1652. BOOL
  1653. TRUE - socket reset (closed by server)
  1654. FALSE - socket alive
  1655. --*/
  1656. {
  1657. DEBUG_ENTER((DBG_SOCKETS,
  1658. Bool,
  1659. "ICSocket::IsReset",
  1660. "{%#x [%#x/%d]}",
  1661. this,
  1662. GetSocket(),
  1663. GetSourcePort()
  1664. ));
  1665. CHECK_ICSOCKET();
  1666. BOOL bReset = FALSE;
  1667. BOOL bSetBlocking = FALSE;
  1668. if (IsOpen()) {
  1669. if (!IsNonBlocking()) {
  1670. SetNonBlockingMode(TRUE);
  1671. bSetBlocking = TRUE;
  1672. }
  1673. char ch;
  1674. #ifndef unix
  1675. int n = _I_recv(m_Socket, &ch, 1, MSG_PEEK);
  1676. if (n < 0) {
  1677. DWORD error = _I_WSAGetLastError();
  1678. if (error != WSAEWOULDBLOCK) {
  1679. DEBUG_PRINT(SOCKETS,
  1680. INFO,
  1681. ("recv() returns %s (%d)\n",
  1682. InternetMapError(error),
  1683. error
  1684. ));
  1685. n = 0;
  1686. }
  1687. }
  1688. if (n == 0) {
  1689. #else
  1690. DWORD dwAvail = 0;
  1691. int n = _I_ioctlsocket(m_Socket,FIONREAD,&dwAvail);
  1692. if (n != 0) {
  1693. #endif /* unix */
  1694. DEBUG_PRINT(SOCKETS,
  1695. INFO,
  1696. ("socket %#x/port %d is reset\n",
  1697. m_Socket,
  1698. m_SourcePort
  1699. ));
  1700. bReset = TRUE;
  1701. }
  1702. if (bSetBlocking) {
  1703. SetNonBlockingMode(FALSE);
  1704. }
  1705. } else {
  1706. bReset = TRUE;
  1707. }
  1708. DEBUG_LEAVE(bReset);
  1709. return bReset;
  1710. }
  1711. DWORD
  1712. ICSocket::SetTimeout(
  1713. IN DWORD Type,
  1714. IN int Timeout
  1715. )
  1716. /*++
  1717. Routine Description:
  1718. Sets a timeout value for a connected socket
  1719. Arguments:
  1720. Type - type of timeout to set - send, or receive
  1721. Timeout - timeout value to set
  1722. Return Value:
  1723. DWORD
  1724. Success - ERROR_SUCCESS
  1725. Failure - WSA error
  1726. --*/
  1727. {
  1728. DEBUG_ENTER((DBG_SOCKETS,
  1729. Dword,
  1730. "ICSocket::SetTimeout",
  1731. "{%#x/%d} %s (%d), %d",
  1732. GetSocket(),
  1733. GetSourcePort(),
  1734. (Type == SEND_TIMEOUT) ? "SEND_TIMEOUT"
  1735. : (Type == RECEIVE_TIMEOUT) ? "RECEIVE_TIMEOUT"
  1736. : "?",
  1737. Type,
  1738. Timeout
  1739. ));
  1740. INET_ASSERT((Type == SEND_TIMEOUT) || (Type == RECEIVE_TIMEOUT));
  1741. if (Timeout == INFINITE)
  1742. {
  1743. Timeout = 0;
  1744. }
  1745. int serr = _I_setsockopt(m_Socket,
  1746. SOL_SOCKET,
  1747. (Type == SEND_TIMEOUT)
  1748. ? SO_SNDTIMEO
  1749. : SO_RCVTIMEO,
  1750. (const char FAR *)&Timeout,
  1751. sizeof(Timeout)
  1752. );
  1753. DWORD error = ERROR_SUCCESS;
  1754. if (serr == SOCKET_ERROR) {
  1755. if (IsAborted()) {
  1756. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1757. } else {
  1758. error = MapInternetError(_I_WSAGetLastError());
  1759. }
  1760. }
  1761. DEBUG_LEAVE(error);
  1762. return error;
  1763. }
  1764. DWORD
  1765. ICSocket::SetLinger(
  1766. IN BOOL Linger,
  1767. IN int Timeout
  1768. )
  1769. /*++
  1770. Routine Description:
  1771. Sets the linger option for a connected socket
  1772. Arguments:
  1773. Linger - FALSE if the caller wants immediate shutdown of the socket
  1774. when closed, or TRUE if we are to wait around until
  1775. queued data has been sent
  1776. Timeout - timeout value to use if Linger is TRUE
  1777. Return Value:
  1778. DWORD
  1779. Success - ERROR_SUCESS
  1780. Failure - WSA error
  1781. --*/
  1782. {
  1783. DEBUG_ENTER((DBG_SOCKETS,
  1784. Dword,
  1785. "ICSocket::SetLinger",
  1786. "{%#x/%d} %B, %d",
  1787. GetSocket(),
  1788. GetSourcePort(),
  1789. Linger,
  1790. Timeout
  1791. ));
  1792. DWORD error = ERROR_SUCCESS;
  1793. if (IsAborted()) {
  1794. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1795. } else if (IsOpen()) {
  1796. LINGER linger;
  1797. INET_ASSERT(Timeout <= USHRT_MAX);
  1798. linger.l_onoff = (u_short)(Linger ? 1 : 0);
  1799. linger.l_linger = (u_short)Timeout;
  1800. //
  1801. // in some shutdown situations, we are hitting exception in winsock
  1802. // on win95 (!). Handle exception
  1803. //
  1804. __try {
  1805. if (_I_setsockopt(m_Socket,
  1806. SOL_SOCKET,
  1807. SO_LINGER,
  1808. (const char FAR *)&linger,
  1809. sizeof(linger)
  1810. ) == SOCKET_ERROR) {
  1811. error = MapInternetError(_I_WSAGetLastError());
  1812. }
  1813. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1814. //
  1815. // do nothing except catch exception in retail
  1816. //
  1817. DEBUG_PRINT(SOCKETS,
  1818. ERROR,
  1819. ("exception closing socket %#x/%d\n",
  1820. GetSocket(),
  1821. GetSourcePort()
  1822. ));
  1823. INET_ASSERT(IsOpen());
  1824. }
  1825. ENDEXCEPT
  1826. }
  1827. DEBUG_LEAVE(error);
  1828. return error;
  1829. }
  1830. DWORD
  1831. ICSocket::SetNonBlockingMode(
  1832. IN BOOL bNonBlocking
  1833. )
  1834. /*++
  1835. Routine Description:
  1836. Sets socket non-blocking/blocking mode
  1837. Arguments:
  1838. bNonBlocking - TRUE if non-blocking, FALSE if blocking
  1839. Return Value:
  1840. DWORD
  1841. Success - ERROR_SUCCESS
  1842. Failure - WSA error mapped to INTERNET error
  1843. --*/
  1844. {
  1845. DEBUG_ENTER((DBG_SOCKETS,
  1846. Dword,
  1847. "ICSocket::SetNonBlockingMode",
  1848. "{%#x/%d} %B",
  1849. GetSocket(),
  1850. GetSourcePort(),
  1851. bNonBlocking
  1852. ));
  1853. u_long on = (bNonBlocking) ? 1 : 0;
  1854. DWORD error = ERROR_SUCCESS;
  1855. if (_I_ioctlsocket(m_Socket, FIONBIO, &on) == 0) {
  1856. if (on) {
  1857. m_dwFlags |= SF_NON_BLOCKING;
  1858. } else {
  1859. m_dwFlags &= ~SF_NON_BLOCKING;
  1860. }
  1861. } else {
  1862. DEBUG_PRINT(SOCKETS,
  1863. ERROR,
  1864. ("failed to put socket %#x/port %d into %sblocking mode\n",
  1865. m_Socket,
  1866. m_SourcePort,
  1867. on ? "non-" : ""
  1868. ));
  1869. if (IsAborted()) {
  1870. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1871. } else {
  1872. error = MapInternetError(_I_WSAGetLastError());
  1873. }
  1874. }
  1875. DEBUG_LEAVE(error);
  1876. return error;
  1877. }
  1878. DWORD
  1879. ICSocket::GetBufferLength(
  1880. IN SOCKET_BUFFER_ID SocketBufferId
  1881. )
  1882. /*++
  1883. Routine Description:
  1884. Returns the send or receive buffer length for this socket object
  1885. Arguments:
  1886. SocketBufferId - which buffer length to return
  1887. Return Value:
  1888. DWORD
  1889. --*/
  1890. {
  1891. //
  1892. // BUGBUG - RLF 04/29/96
  1893. //
  1894. // This function should access first the current object, then the parent
  1895. // object, then the globals for this data
  1896. //
  1897. switch (SocketBufferId) {
  1898. case ReceiveBuffer:
  1899. return GlobalSocketReceiveBufferLength;
  1900. case SendBuffer:
  1901. return GlobalSocketSendBufferLength;
  1902. }
  1903. return (DWORD)-1;
  1904. }
  1905. DWORD
  1906. ICSocket::GetBufferLength(
  1907. IN SOCKET_BUFFER_ID SocketBufferId,
  1908. OUT LPDWORD lpdwBufferLength
  1909. )
  1910. /*++
  1911. Routine Description:
  1912. Gets the socket send or receive buffer length (if supported)
  1913. Arguments:
  1914. SocketBufferId - which buffer to set
  1915. lpdwBufferLength - where to write length
  1916. Return Value:
  1917. DWORD
  1918. Success - ERROR_SUCCESS
  1919. Failure -
  1920. --*/
  1921. {
  1922. DEBUG_ENTER((DBG_SOCKETS,
  1923. Int,
  1924. "ICSocket::GetBufferLength",
  1925. "{%#x/%d} %s, %#x",
  1926. GetSocket(),
  1927. GetSourcePort(),
  1928. (SocketBufferId == ReceiveBuffer)
  1929. ? "ReceiveBuffer"
  1930. : ((SocketBufferId == SendBuffer)
  1931. ? "SendBuffer"
  1932. : "?")
  1933. ));
  1934. DWORD size = sizeof(*lpdwBufferLength);
  1935. int serr = _I_getsockopt(m_Socket,
  1936. SOL_SOCKET,
  1937. SocketBufferId,
  1938. (char FAR *)lpdwBufferLength,
  1939. (int FAR *)&size
  1940. );
  1941. DWORD error;
  1942. if (serr != SOCKET_ERROR) {
  1943. error = ERROR_SUCCESS;
  1944. } else {
  1945. error = MapInternetError(_I_WSAGetLastError());
  1946. }
  1947. DEBUG_LEAVE(error);
  1948. return error;
  1949. }
  1950. DWORD
  1951. ICSocket::SetBufferLength(
  1952. IN SOCKET_BUFFER_ID SocketBufferId,
  1953. IN DWORD dwBufferLength
  1954. )
  1955. /*++
  1956. Routine Description:
  1957. Sets the socket send or receive buffer length
  1958. Arguments:
  1959. SocketBufferId - which buffer to set
  1960. dwBufferLength - length to set it to
  1961. Return Value:
  1962. DWORD
  1963. Success - ERROR_SUCCESS
  1964. Failure - WSA error mapped to INTERNET error
  1965. --*/
  1966. {
  1967. DEBUG_ENTER((DBG_SOCKETS,
  1968. Dword,
  1969. "ICSocket::SetBufferLength",
  1970. "{%#x/%d} %s, %d",
  1971. GetSocket(),
  1972. GetSourcePort(),
  1973. (SocketBufferId == ReceiveBuffer)
  1974. ? "ReceiveBuffer"
  1975. : (SocketBufferId == SendBuffer)
  1976. ? "SendBuffer"
  1977. : "?",
  1978. dwBufferLength
  1979. ));
  1980. INET_ASSERT((int)dwBufferLength >= 0);
  1981. DWORD size = sizeof(dwBufferLength);
  1982. int serr = _I_setsockopt(m_Socket,
  1983. SOL_SOCKET,
  1984. SocketBufferId,
  1985. (const char FAR *)&dwBufferLength,
  1986. (int)size
  1987. );
  1988. DWORD error = ERROR_SUCCESS;
  1989. if (serr == SOCKET_ERROR) {
  1990. if (IsAborted()) {
  1991. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  1992. } else {
  1993. error = MapInternetError(_I_WSAGetLastError());
  1994. }
  1995. }
  1996. DEBUG_LEAVE(error);
  1997. return error;
  1998. }
  1999. DWORD
  2000. ICSocket::SetSendCoalescing(
  2001. IN BOOL bOnOff
  2002. )
  2003. /*++
  2004. Routine Description:
  2005. Enables or disables Nagle algorithm
  2006. Arguments:
  2007. bOnOff - FALSE to disable, TRUE to enable
  2008. Return Value:
  2009. DWORD
  2010. Success - ERROR_SUCCESS
  2011. Failure -
  2012. --*/
  2013. {
  2014. DEBUG_ENTER((DBG_SOCKETS,
  2015. Dword,
  2016. "ICSocket::SetSendCoalescing",
  2017. "{%#x/%d} %B",
  2018. GetSocket(),
  2019. GetSourcePort(),
  2020. bOnOff
  2021. ));
  2022. int optval = bOnOff ? 0 : 1;
  2023. int serr = _I_setsockopt(m_Socket,
  2024. IPPROTO_TCP,
  2025. TCP_NODELAY,
  2026. (const char FAR *)&optval,
  2027. sizeof(optval)
  2028. );
  2029. DWORD error = ERROR_SUCCESS;
  2030. if (serr == SOCKET_ERROR) {
  2031. if (IsAborted()) {
  2032. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2033. } else {
  2034. error = MapInternetError(_I_WSAGetLastError());
  2035. }
  2036. }
  2037. DEBUG_LEAVE(error);
  2038. return error;
  2039. }
  2040. VOID
  2041. ICSocket::SetSourcePort(
  2042. VOID
  2043. )
  2044. /*++
  2045. Routine Description:
  2046. Record the port we are connected to locally. Useful for debugging & matching
  2047. up socket with net sniff
  2048. Arguments:
  2049. None.
  2050. Return Value:
  2051. None.
  2052. --*/
  2053. {
  2054. sockaddr_storage address; // Large enough for any address family.
  2055. int namelen = sizeof(address);
  2056. if (_I_getsockname(GetSocket(), (LPSOCKADDR)&address, &namelen) == 0) {
  2057. //
  2058. // The port number field is in the same location in both a
  2059. // sockaddr_in and a sockaddr_in6, so it is safe to cast the
  2060. // sockaddr to sockaddr_in here - this works for IPv4 or IPv6.
  2061. //
  2062. INET_ASSERT(offsetof(SOCKADDR_IN, sin_port) == offsetof(SOCKADDR_IN6, sin6_port));
  2063. m_SourcePort = (INTERNET_PORT)_I_ntohs(((LPSOCKADDR_IN)&address)->sin_port);
  2064. } else {
  2065. m_SourcePort = 0;
  2066. }
  2067. }
  2068. DWORD
  2069. ICSocket::Send(
  2070. IN LPVOID lpBuffer,
  2071. IN DWORD dwBufferLength,
  2072. IN DWORD dwFlags
  2073. )
  2074. /*++
  2075. Routine Description:
  2076. Sends data over connected socket
  2077. Arguments:
  2078. lpBuffer - pointer to buffer containing data to send
  2079. dwBufferLength - length of lpBuffer in bytes
  2080. dwFlags - flags controlling send:
  2081. SF_INDICATE - make status callbacks to the app when
  2082. we are starting to send data and when
  2083. we finish
  2084. Return Value:
  2085. DWORD
  2086. Success - ERROR_SUCCESS
  2087. ERROR_IO_PENDING
  2088. Operation will complete asynchronously
  2089. Failure - ERROR_NOT_ENOUGH_MEMORY
  2090. Couldn't create FSM
  2091. --*/
  2092. {
  2093. DEBUG_ENTER((DBG_SOCKETS,
  2094. Dword,
  2095. "ICSocket::Send",
  2096. "{%#x [%#x/%d]} %#x, %d, %#x",
  2097. this,
  2098. GetSocket(),
  2099. GetSourcePort(),
  2100. lpBuffer,
  2101. dwBufferLength,
  2102. dwFlags
  2103. ));
  2104. INET_ASSERT(lpBuffer != NULL);
  2105. INET_ASSERT((int)dwBufferLength > 0);
  2106. DWORD error = DoFsm(New CFsm_SocketSend(lpBuffer,
  2107. dwBufferLength,
  2108. dwFlags,
  2109. this
  2110. ));
  2111. DEBUG_LEAVE(error);
  2112. return error;
  2113. }
  2114. DWORD
  2115. CFsm_SocketSend::RunSM(
  2116. IN CFsm * Fsm
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. Runs next CFsm_SocketSend state
  2121. Arguments:
  2122. Fsm - socket send FSM
  2123. Return Value:
  2124. DWORD
  2125. Success - ERROR_SUCCESS
  2126. ERROR_IO_PENDING
  2127. Operation will complete asynchronously
  2128. Failure -
  2129. --*/
  2130. {
  2131. DEBUG_ENTER((DBG_SOCKETS,
  2132. Dword,
  2133. "CFsm_SocketSend::RunSM",
  2134. "%#x",
  2135. Fsm
  2136. ));
  2137. ICSocket * pSocket = (ICSocket *)Fsm->GetContext();
  2138. CFsm_SocketSend * stateMachine = (CFsm_SocketSend *)Fsm;
  2139. DWORD error;
  2140. switch (Fsm->GetState()) {
  2141. case FSM_STATE_INIT:
  2142. case FSM_STATE_CONTINUE:
  2143. case FSM_STATE_ERROR:
  2144. error = pSocket->Send_Start(stateMachine);
  2145. break;
  2146. default:
  2147. error = ERROR_WINHTTP_INTERNAL_ERROR;
  2148. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  2149. INET_ASSERT(FALSE);
  2150. break;
  2151. }
  2152. DEBUG_LEAVE(error);
  2153. return error;
  2154. }
  2155. DWORD
  2156. ICSocket::Send_Start(
  2157. IN CFsm_SocketSend * Fsm
  2158. )
  2159. /*++
  2160. Routine Description:
  2161. Continues send request - sends the data
  2162. Arguments:
  2163. Fsm - socket send FSM
  2164. Return Value:
  2165. DWORD
  2166. Success - ERROR_SUCCESS
  2167. ERROR_IO_PENDING
  2168. Operation will complete asynchronously
  2169. Failure -
  2170. --*/
  2171. {
  2172. DEBUG_ENTER((DBG_SOCKETS,
  2173. Dword,
  2174. "ICSocket::Send_Start",
  2175. "{%#x [%#x/%d]} %#x(%#x, %d, %#x)",
  2176. this,
  2177. GetSocket(),
  2178. GetSourcePort(),
  2179. Fsm,
  2180. Fsm->m_lpBuffer,
  2181. Fsm->m_dwBufferLength,
  2182. Fsm->m_dwFlags
  2183. ));
  2184. CFsm_SocketSend & fsm = *Fsm;
  2185. DWORD error = fsm.GetError();
  2186. FSM_STATE state = fsm.GetState();
  2187. INTERNET_HANDLE_OBJECT * pObject = fsm.GetMappedHandleObject();
  2188. if (error != ERROR_SUCCESS)
  2189. {
  2190. goto quit;
  2191. }
  2192. if (state == FSM_STATE_INIT) {
  2193. if (!(m_dwFlags & (SF_ENCRYPT | SF_DECRYPT))) {
  2194. DEBUG_DUMP_API(SOCKETS,
  2195. "sending data:\n",
  2196. fsm.m_lpBuffer,
  2197. fsm.m_dwBufferLength
  2198. );
  2199. TRACE_DUMP_API_IF_REQUEST(SOCKETS,
  2200. "sending data:\n",
  2201. fsm.m_lpBuffer,
  2202. fsm.m_dwBufferLength,
  2203. (HANDLE_OBJECT *)(fsm.GetMappedHandle())
  2204. );
  2205. }
  2206. if (pObject != NULL) {
  2207. pObject->SetAbortHandle(this);
  2208. }
  2209. if (fsm.m_dwFlags & SF_INDICATE) {
  2210. error = InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0);
  2211. if (error != ERROR_SUCCESS)
  2212. {
  2213. INET_ASSERT(error == ERROR_WINHTTP_OPERATION_CANCELLED);
  2214. goto quit;
  2215. }
  2216. }
  2217. fsm.StartTimer();
  2218. }
  2219. while (fsm.m_dwBufferLength != 0)
  2220. {
  2221. //
  2222. // the socket may have already been aborted
  2223. //
  2224. if (IsAborted()) {
  2225. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2226. break;
  2227. }
  2228. if (fsm.m_pServerInfo != NULL) {
  2229. fsm.m_pServerInfo->SetLastActiveTime();
  2230. }
  2231. DWORD dwSendSize;
  2232. #define GLOBAL_MAX_SEND_LENGTH_DEFAULT (4*1024*1024)
  2233. if (fsm.m_dwBufferLength > GLOBAL_MAX_SEND_LENGTH_DEFAULT)
  2234. {
  2235. dwSendSize = GLOBAL_MAX_SEND_LENGTH_DEFAULT;
  2236. }
  2237. else
  2238. {
  2239. dwSendSize = fsm.m_dwBufferLength;
  2240. }
  2241. int nSent;
  2242. if (IsNonBlocking())
  2243. {
  2244. if (fsm.bIOCPInited)
  2245. {
  2246. fsm.bIOCPInited = FALSE;
  2247. if (fsm.bIOCPSuccess)
  2248. {
  2249. //send completed successfully
  2250. DEBUG_PRINT(SOCKETS,
  2251. INFO,
  2252. ("WSASend sent %d bytes @ %#x to socket %#x/port %d\n",
  2253. fsm.dwBytesTransferred,
  2254. fsm.m_lpBuffer,
  2255. m_Socket,
  2256. m_SourcePort
  2257. ));
  2258. error = ERROR_SUCCESS;
  2259. nSent = (int)fsm.dwBytesTransferred;
  2260. fsm.m_iTotalSent = nSent;
  2261. fsm.m_lpBuffer = (LPBYTE)fsm.m_lpBuffer + nSent;
  2262. fsm.m_dwBufferLength -= nSent;
  2263. continue;
  2264. }
  2265. else
  2266. {
  2267. //
  2268. // map any sockets error to WinHttp error and terminate this
  2269. // request
  2270. //
  2271. //VENKATKBUG - handle retrieable errors such as WSAWOULDBLOCK
  2272. DEBUG_PRINT(SOCKETS,
  2273. ERROR,
  2274. ("send() returns %d (%s)\n",
  2275. error,
  2276. InternetMapError(error)
  2277. ));
  2278. error = MapInternetError(error);
  2279. break;
  2280. }
  2281. }// if fsm.bIOCPInited()
  2282. WSABUF wsabuf;
  2283. wsabuf.len = dwSendSize; //fsm.m_dwBufferLength;
  2284. wsabuf.buf = (char FAR *)fsm.m_lpBuffer;
  2285. int nError;
  2286. //
  2287. // First try Winsock Fast I/O: see if Winsock can
  2288. // satisfy the send call immediately. If it fails,
  2289. // we assume the error is WSAWOULDBLOCK and then
  2290. // try WSASend again with the lpOverlapped parameter.
  2291. //
  2292. nError = _I_WSASend(m_Socket,
  2293. &wsabuf,
  2294. 1,
  2295. (LPDWORD)&nSent,
  2296. 0,
  2297. NULL,
  2298. NULL);
  2299. if (nError == 0)
  2300. {
  2301. fsm.m_iTotalSent = nSent;
  2302. fsm.m_lpBuffer = (LPBYTE)fsm.m_lpBuffer + nSent;
  2303. fsm.m_dwBufferLength -= nSent;
  2304. continue;
  2305. }
  2306. else
  2307. {
  2308. INET_ASSERT (nError == SOCKET_ERROR);
  2309. error = _I_WSAGetLastError();
  2310. }
  2311. //
  2312. // Slow path: issue an async recv call, with the results
  2313. // to be posted to our I/O completion port.
  2314. //
  2315. if (!_lpWrapOverlappedSend)
  2316. {
  2317. _lpWrapOverlappedSend = New CWrapOverlapped();
  2318. if (!_lpWrapOverlappedSend)
  2319. {
  2320. error = ERROR_NOT_ENOUGH_MEMORY;
  2321. goto quit;
  2322. }
  2323. }
  2324. CWrapOverlapped* lpWrapOverlapped = _lpWrapOverlappedSend;
  2325. LPWSAOVERLAPPED lpOverlapped = _lpWrapOverlappedSend->GetOverlapped();
  2326. memset(lpOverlapped, 0, sizeof(WSAOVERLAPPED));
  2327. CFsm* pFsmOld = GetAndSetCurrentFsm(&fsm);
  2328. UNREFERENCED_PARAMETER(pFsmOld); // eliminate C4701 in free builds
  2329. INET_ASSERT (pFsmOld == NULL);
  2330. fsm.bIOCPInited = TRUE;
  2331. DEBUG_PRINT(SOCKETS,
  2332. INFO,
  2333. ("calling WSASend() blocked, socket %#x, port %d\n",
  2334. m_Socket,
  2335. m_SourcePort
  2336. ));
  2337. fsm.SetAction(FSM_ACTION_SEND);
  2338. DWORD timeout = GetTimeoutValue(WINHTTP_OPTION_SEND_TIMEOUT);
  2339. if (timeout != INFINITE)
  2340. {
  2341. fsm.SetTimeout(timeout);
  2342. #ifdef USE_OLD_SENDRECV_SYNC
  2343. fsm.SetOnAsyncList(TRUE);
  2344. #else
  2345. //additional reference for timeout queue
  2346. fsm.Reference();
  2347. fsm.SetPop(FALSE);
  2348. #endif
  2349. if (Fsm->GetMappedHandleObject())
  2350. {
  2351. Fsm->GetMappedHandleObject()->Reference();
  2352. }
  2353. error = QueueTimeoutFsm(Fsm, m_Socket);
  2354. if (error != ERROR_IO_PENDING)
  2355. {
  2356. // 2 causes - both irrecoverable
  2357. // 1. no global pointer to ICAsyncThread (impossible)
  2358. // OR 2. no threadinfo or SelectThread or out of memory.
  2359. // so bail!
  2360. GetAndSetCurrentFsm(NULL);
  2361. fsm.bIOCPInited = FALSE;
  2362. #ifdef USE_OLD_SENDRECV_SYNC
  2363. fsm.SetOnAsyncList(FALSE);
  2364. #else
  2365. if (Fsm->GetMappedHandleObject())
  2366. {
  2367. Fsm->GetMappedHandleObject()->Dereference();
  2368. }
  2369. DWORD dwDummy = 0;
  2370. fsm.Dereference(&dwDummy);
  2371. #endif
  2372. fsm.SetErrorState(error);
  2373. goto quit;
  2374. }
  2375. }
  2376. _lpWrapOverlappedSend->Reference(); // to keep this ICSocket=>the Overlapped struct valid beyong the WSASend() call.
  2377. _lpWrapOverlappedSend->Reference(); // to make sure it stays alive for the IOCP to get the fsm off it.
  2378. DEBUG_ENTER((DBG_API,
  2379. Dword,
  2380. "***WSASend",
  2381. "(m_Socket)%#x, (wsabuf.buf)%#x, (wsabuf.len)%#x, (this)%#x, (overlapped)%#x, (fsm)%#x",
  2382. m_Socket,
  2383. wsabuf.buf,
  2384. wsabuf.len,
  2385. this,
  2386. lpOverlapped,
  2387. &fsm
  2388. ));
  2389. nError = _I_WSASend(m_Socket,
  2390. &wsabuf,
  2391. 1,
  2392. (LPDWORD)&nSent,
  2393. 0,
  2394. lpOverlapped,
  2395. NULL);
  2396. DEBUG_LEAVE(nError);
  2397. lpWrapOverlapped->Dereference(); // release the WSASend reference.
  2398. DEBUG_PRINT(SOCKETS,
  2399. ERROR,
  2400. ("WSASend() returns %d (%s) with nSent=%d bytes\n",
  2401. nError,
  2402. InternetMapError(nError),
  2403. nSent
  2404. ));
  2405. if (nError == 0)
  2406. {
  2407. #if INET_DEBUG
  2408. InterlockedIncrement(&g_cWSACompletions);
  2409. #endif
  2410. error = ERROR_IO_PENDING;
  2411. break;
  2412. }
  2413. else
  2414. {
  2415. INET_ASSERT (nError == SOCKET_ERROR);
  2416. error = _I_WSAGetLastError();
  2417. if (error == WSA_IO_PENDING)
  2418. {
  2419. #if INET_DEBUG
  2420. InterlockedIncrement(&g_cWSACompletions);
  2421. #endif
  2422. error = ERROR_IO_PENDING;
  2423. break;
  2424. }
  2425. else
  2426. {
  2427. // no IOCompletion here.
  2428. if (fsm.HasTimeout())
  2429. {
  2430. #ifdef USE_OLD_SENDRECV_SYNC
  2431. if (!RemoveFsmFromAsyncList(&fsm))
  2432. {
  2433. //the select thread already enforced timeout and updated state
  2434. }
  2435. #else
  2436. if (!fsm.TestAndSetValidForIOCPProcessing())
  2437. {
  2438. //the select thread already enforced timeout and updated state
  2439. }
  2440. #endif
  2441. }
  2442. GetAndSetCurrentFsm(NULL);
  2443. lpWrapOverlapped->Dereference(); // release the IOCP-based reference.
  2444. //
  2445. // check first to see if the error was due to the socket being
  2446. // closed as a result of the request being cancelled
  2447. //
  2448. if (IsAborted())
  2449. {
  2450. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2451. break;
  2452. }
  2453. //
  2454. // map any sockets error to WinHttp error and terminate this
  2455. // request
  2456. //
  2457. error = MapInternetError(error);
  2458. break;
  2459. }
  2460. }//if! nError == 0
  2461. }
  2462. else// if IsNonBlocking()
  2463. {
  2464. nSent = _I_send(m_Socket,
  2465. (char FAR *)fsm.m_lpBuffer,
  2466. dwSendSize, //fsm.m_dwBufferLength,
  2467. 0
  2468. );
  2469. if (nSent != SOCKET_ERROR)
  2470. {
  2471. DEBUG_PRINT(SOCKETS,
  2472. INFO,
  2473. ("sent %d bytes @ %#x to socket %#x/port %d\n",
  2474. nSent,
  2475. fsm.m_lpBuffer,
  2476. m_Socket,
  2477. m_SourcePort
  2478. ));
  2479. fsm.m_iTotalSent += nSent;
  2480. fsm.m_lpBuffer = (LPBYTE)fsm.m_lpBuffer + nSent;
  2481. fsm.m_dwBufferLength -= nSent;
  2482. }
  2483. else
  2484. {
  2485. //
  2486. // check first to see if the error was due to the socket being
  2487. // closed as a result of the request being cancelled
  2488. //
  2489. if (IsAborted())
  2490. {
  2491. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2492. break;
  2493. }
  2494. else
  2495. {
  2496. error = _I_WSAGetLastError();
  2497. //
  2498. // map any sockets error to WinHttp error and terminate this
  2499. // request
  2500. //
  2501. DEBUG_PRINT(SOCKETS,
  2502. ERROR,
  2503. ("send() returns %d (%s)\n",
  2504. error,
  2505. InternetMapError(error)
  2506. ));
  2507. error = MapInternetError(error);
  2508. break;
  2509. }
  2510. }// if! nSent!=SOCKET_ERROR
  2511. }// if! IsNonBlocking()
  2512. }// while fsm.m_dwBufferLength != 0
  2513. quit:
  2514. if (error != ERROR_IO_PENDING) {
  2515. fsm.StopTimer();
  2516. if (fsm.GetMappedHandleObject() != NULL) {
  2517. fsm.GetMappedHandleObject()->ResetAbortHandle();
  2518. }
  2519. if (IsAborted()) {
  2520. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2521. } else if (error == ERROR_SUCCESS) {
  2522. if (fsm.m_dwFlags & SF_INDICATE)
  2523. {
  2524. INT iTotalSent = fsm.m_iTotalSent;
  2525. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_REQUEST_SENT,
  2526. &iTotalSent,
  2527. sizeof(iTotalSent)
  2528. );
  2529. }
  2530. if (fsm.m_pServerInfo != NULL) {
  2531. //fsm.m_pServerInfo->UpdateSendTime(fsm.ReadTimer());
  2532. }
  2533. }
  2534. fsm.SetDone(error);
  2535. }
  2536. DEBUG_LEAVE(error);
  2537. return error;
  2538. }
  2539. //
  2540. //DWORD
  2541. //ICSocket::SendTo(
  2542. // IN LPSOCKADDR lpDestination,
  2543. // IN DWORD dwDestinationLength,
  2544. // IN LPVOID lpBuffer,
  2545. // IN DWORD dwBufferLength,
  2546. // OUT LPDWORD lpdwBytesSent,
  2547. // IN DWORD dwWinsockFlags,
  2548. // IN DWORD dwFlags
  2549. // )
  2550. //
  2551. ///*++
  2552. //
  2553. //Routine Description:
  2554. //
  2555. // Wrapper for sendto()
  2556. //
  2557. //Arguments:
  2558. //
  2559. // lpDestination - pointer to remote address to send to
  2560. //
  2561. // dwDestinationLength - length of *lpDestination
  2562. //
  2563. // lpBuffer - pointer to buffer containing data to send
  2564. //
  2565. // dwBufferLength - number of bytes to send from lpBuffer
  2566. //
  2567. // lpdwBytesSent - number of bytes sent to destination
  2568. //
  2569. // dwWinsockFlags - flags to pass through to sendto()
  2570. //
  2571. // dwFlags - ICSocket flags
  2572. //
  2573. //Return Value:
  2574. //
  2575. // DWORD
  2576. // Success - ERROR_SUCCESS
  2577. //
  2578. // Failure - ERROR_WINHTTP_OPERATION_CANCELLED
  2579. // The operation was cancelled by the caller
  2580. //
  2581. // ERROR_WINHTTP_TIMEOUT
  2582. // The operation timed out
  2583. //
  2584. // ERROR_WINHTTP_CONNECTION_ERROR
  2585. // An error occurred. We approximate to connection reset
  2586. //
  2587. // WSA error
  2588. // Some other sockets error occurred
  2589. //
  2590. //--*/
  2591. //
  2592. //{
  2593. // DEBUG_ENTER((DBG_SOCKETS,
  2594. // Dword,
  2595. // "ICSocket::SendTo",
  2596. // "{%#x} %#x, %d, %#x, %d, %#x, %#x, %#x",
  2597. // m_Socket,
  2598. // lpDestination,
  2599. // dwDestinationLength,
  2600. // lpBuffer,
  2601. // dwBufferLength,
  2602. // lpdwBytesSent,
  2603. // dwWinsockFlags,
  2604. // dwFlags
  2605. // ));
  2606. //
  2607. // INET_ASSERT(IsSocketValid());
  2608. // INET_ASSERT(lpdwBytesSent != NULL);
  2609. //
  2610. // int totalSent = 0;
  2611. // DWORD error = ERROR_SUCCESS;
  2612. // INTERNET_HANDLE_OBJECT * pObject = NULL;
  2613. // LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  2614. // BOOL fNonBlocking;
  2615. //
  2616. // if (IsAborted()) {
  2617. // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2618. // goto quit;
  2619. // }
  2620. //
  2621. // if (lpThreadInfo == NULL) {
  2622. //
  2623. // INET_ASSERT(FALSE);
  2624. //
  2625. // error = ERROR_WINHTTP_INTERNAL_ERROR;
  2626. // goto quit;
  2627. // }
  2628. //
  2629. // fNonBlocking = lpThreadInfo->IsAsyncWorkerThread;
  2630. //
  2631. // //
  2632. // // set the cancel socket in the object
  2633. // //
  2634. //
  2635. // pObject = (INTERNET_HANDLE_OBJECT * )lpThreadInfo->hObjectMapped;
  2636. // if (pObject != NULL) {
  2637. // pObject->SetAbortHandle(this);
  2638. // }
  2639. //
  2640. // //
  2641. // // if we are in async (== non-blocking) mode, let the async request
  2642. // // scheduler know what operation we will be waiting on
  2643. // //
  2644. //
  2645. // if (fNonBlocking) {
  2646. //
  2647. // INET_ASSERT(lpThreadInfo->lpArb != NULL);
  2648. //
  2649. // SET_ARB_SOCKET_OPERATION(lpThreadInfo->lpArb, m_Socket, SEND);
  2650. // }
  2651. //
  2652. // if (dwFlags & SF_INDICATE) {
  2653. //
  2654. // //
  2655. // // let the app know we are starting to send data
  2656. // //
  2657. //
  2658. // InternetIndicateStatus(INTERNET_STATUS_SENDING_REQUEST,
  2659. // NULL,
  2660. // 0
  2661. // );
  2662. // }
  2663. //
  2664. // DEBUG_DUMP(SOCKETS,
  2665. // "sending data:\n",
  2666. // lpBuffer,
  2667. // dwBufferLength
  2668. // );
  2669. //
  2670. // int nSent;
  2671. //
  2672. // //
  2673. // // loop until all data sent
  2674. // //
  2675. //
  2676. // do {
  2677. //
  2678. // nSent = _I_sendto(m_Socket,
  2679. // (char FAR *)lpBuffer + totalSent,
  2680. // dwBufferLength,
  2681. // dwWinsockFlags,
  2682. // lpDestination,
  2683. // dwDestinationLength
  2684. // );
  2685. // if (nSent != SOCKET_ERROR) {
  2686. //
  2687. // DEBUG_PRINT(SOCKETS,
  2688. // INFO,
  2689. // ("sent %d bytes @ %#x on socket %#x\n",
  2690. // nSent,
  2691. // (LPBYTE)lpBuffer + totalSent,
  2692. // m_Socket
  2693. // ));
  2694. //
  2695. // INET_ASSERT(nSent > 0);
  2696. //
  2697. // totalSent += nSent;
  2698. // dwBufferLength -= nSent;
  2699. // } else {
  2700. // error = _I_WSAGetLastError();
  2701. // if ((error == WSAEWOULDBLOCK) && fNonBlocking) {
  2702. //
  2703. // INET_ASSERT(_dwFlags & SF_NON_BLOCKING);
  2704. //
  2705. // DEBUG_PRINT(SOCKETS,
  2706. // INFO,
  2707. // ("sendto(%#x) would block\n",
  2708. // m_Socket
  2709. // ));
  2710. //
  2711. // lpThreadInfo->lpArb->Header.dwResultCode = ERROR_SUCCESS;
  2712. //
  2713. // SwitchToAsyncScheduler(m_Socket);
  2714. //
  2715. // error = lpThreadInfo->lpArb->Header.dwResultCode;
  2716. //
  2717. // DEBUG_PRINT(SOCKETS,
  2718. // INFO,
  2719. // ("sendto(%#x) resumed, returns %s\n",
  2720. // m_Socket,
  2721. // InternetMapError(error)
  2722. // ));
  2723. //
  2724. // if (error != ERROR_SUCCESS) {
  2725. // }
  2726. // } else {
  2727. //
  2728. // //
  2729. // // some other error
  2730. // //
  2731. //
  2732. // error = MapInternetError(error);
  2733. // }
  2734. // }
  2735. //
  2736. // INET_ASSERT((int)dwBufferLength >= 0);
  2737. //
  2738. // } while ((dwBufferLength != 0) && (error == ERROR_SUCCESS));
  2739. //
  2740. // if ((dwFlags & SF_INDICATE) && (error == ERROR_SUCCESS)) {
  2741. //
  2742. // //
  2743. // // let the app know we have finished sending
  2744. // //
  2745. //
  2746. // InternetIndicateStatus(INTERNET_STATUS_REQUEST_SENT,
  2747. // &totalSent,
  2748. // sizeof(totalSent)
  2749. // );
  2750. // }
  2751. //
  2752. // //
  2753. // // if we are in async (== non-blocking) mode, let the async request
  2754. // // scheduler know that we no longer require this socket
  2755. // //
  2756. //
  2757. // if (fNonBlocking) {
  2758. //
  2759. // INET_ASSERT(lpThreadInfo->lpArb != NULL);
  2760. //
  2761. // SET_ARB_SOCKET_OPERATION(lpThreadInfo->lpArb, INVALID_SOCKET, SEND);
  2762. // }
  2763. //
  2764. //quit:
  2765. //
  2766. // *lpdwBytesSent = totalSent;
  2767. //
  2768. // //
  2769. // // no longer performing operation on this socket
  2770. // //
  2771. //
  2772. // if (pObject != NULL) {
  2773. // pObject->ResetAbortHandle();
  2774. //
  2775. // //
  2776. // // if the operation has been cancelled, then this error overrides any
  2777. // // other
  2778. // //
  2779. //
  2780. // //if (pObject->IsInvalidated()) {
  2781. // // error = pObject->GetError();
  2782. // // if (error == ERROR_SUCCESS) {
  2783. // // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2784. // // }
  2785. // //}
  2786. // if (IsAborted()) {
  2787. // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  2788. // }
  2789. // }
  2790. //
  2791. // INET_ASSERT((pObject != NULL) ? (pObject->GetAbortHandle() == NULL) : TRUE);
  2792. //
  2793. // DEBUG_LEAVE(error);
  2794. //
  2795. // return error;
  2796. //}
  2797. DWORD
  2798. ICSocket::Receive(
  2799. IN OUT LPVOID * lplpBuffer,
  2800. IN OUT LPDWORD lpdwBufferLength,
  2801. IN OUT LPDWORD lpdwBufferRemaining,
  2802. IN OUT LPDWORD lpdwBytesReceived,
  2803. IN DWORD dwExtraSpace,
  2804. IN DWORD dwFlags,
  2805. OUT LPBOOL lpbEof
  2806. )
  2807. /*++
  2808. Routine Description:
  2809. Receives data from connected socket. Depending on flags settings, we will
  2810. perform a single receive, loop until we have filled the buffer and/or loop
  2811. until we have received all the data.
  2812. This function returns user data, so if the stream we are receiving from is
  2813. encrypted, we must decrypt the data before returning. This may require
  2814. receiving more data than the user expects because we have to decrypt at
  2815. message boundaries
  2816. This function is intended to be called in a loop. The buffer pointer and
  2817. buffer sizes are intended to be updated by each successive call to this
  2818. function, and should therefore have the same values the next time this
  2819. function is called
  2820. Arguments:
  2821. lplpBuffer - pointer to pointer to users buffer. If supplied, the
  2822. buffer should be LMEM_FIXED
  2823. lpdwBufferLength - size of buffer
  2824. lpdwBufferRemaining - number of bytes left in the buffer
  2825. lpdwBytesReceived - number of bytes received
  2826. dwExtraSpace - number of additional bytes caller wants at end of
  2827. buffer (only useful if resizing AND only applied at
  2828. end of receive)
  2829. dwFlags - flags controlling receive:
  2830. SF_EXPAND - lpBuffer can be expanded to fit
  2831. data
  2832. SF_COMPRESS - if set, we will shrink the buffer
  2833. to compress out any unused space
  2834. SF_RECEIVE_ALL - if set, this function will loop
  2835. until all data received, or the
  2836. supplied buffer is filled
  2837. SF_INDICATE - if set, we will make status
  2838. callbacks to the app when we are
  2839. starting to receive data, and when
  2840. we finish
  2841. SF_WAIT - (used with SF_NON_BLOCKING). Even
  2842. though the socket is non-blocking,
  2843. the caller wants us to not
  2844. relinquish control under the
  2845. request has been satisfied
  2846. lpbEof - TRUE if we got end-of-connection indication
  2847. (recv() returns 0)
  2848. Return Value:
  2849. DWORD
  2850. Success - ERROR_SUCCESS
  2851. ERROR_IO_PENDING
  2852. Operation will complete asynchronously
  2853. Failure - ERROR_NOT_ENOUGH_MEMORY
  2854. Couldn't allocate/grow buffer
  2855. ERROR_INSUFFICIENT_BUFFER
  2856. The initial buffer was insufficient (i.e. caller supplied
  2857. buffer pointer was NULL, or we ran out of buffer space and
  2858. are not allowed to resize it)
  2859. WSA error
  2860. Sockets error
  2861. --*/
  2862. {
  2863. DEBUG_ENTER((DBG_SOCKETS,
  2864. Dword,
  2865. "ICSocket::Receive",
  2866. "%#x [%#x], %#x [%d], %#x [%d], %#x [%d], %d, %#x, %#x [%B]",
  2867. lplpBuffer,
  2868. *lplpBuffer,
  2869. lpdwBufferLength,
  2870. *lpdwBufferLength,
  2871. lpdwBufferRemaining,
  2872. *lpdwBufferRemaining,
  2873. lpdwBytesReceived,
  2874. *lpdwBytesReceived,
  2875. dwExtraSpace,
  2876. dwFlags,
  2877. lpbEof,
  2878. *lpbEof
  2879. ));
  2880. INET_ASSERT((int)*lpdwBufferLength >= 0);
  2881. INET_ASSERT((int)*lpdwBufferRemaining >= 0);
  2882. INET_ASSERT((int)*lpdwBytesReceived >= 0);
  2883. #define SF_MUTEX_FLAGS (SF_RECEIVE_ALL | SF_NO_WAIT)
  2884. INET_ASSERT((dwFlags & SF_MUTEX_FLAGS) != SF_MUTEX_FLAGS);
  2885. DWORD error = DoFsm(New CFsm_SocketReceive(lplpBuffer,
  2886. lpdwBufferLength,
  2887. lpdwBufferRemaining,
  2888. lpdwBytesReceived,
  2889. dwExtraSpace,
  2890. dwFlags,
  2891. lpbEof,
  2892. this
  2893. ));
  2894. DEBUG_LEAVE(error);
  2895. return error;
  2896. }
  2897. DWORD
  2898. CFsm_SocketReceive::RunSM(
  2899. IN CFsm * Fsm
  2900. )
  2901. /*++
  2902. Routine Description:
  2903. Runs next CFsm_SocketReceive state
  2904. Arguments:
  2905. Fsm - socket receive FSM
  2906. Return Value:
  2907. DWORD
  2908. Success - ERROR_SUCCESS
  2909. ERROR_IO_PENDING
  2910. Operation will complete asynchronously
  2911. Failure -
  2912. --*/
  2913. {
  2914. DEBUG_ENTER((DBG_SOCKETS,
  2915. Dword,
  2916. "CFsm_SocketReceive::RunSM",
  2917. "%#x",
  2918. Fsm
  2919. ));
  2920. ICSocket * pSocket = (ICSocket *)Fsm->GetContext();
  2921. CFsm_SocketReceive * stateMachine = (CFsm_SocketReceive *)Fsm;
  2922. DWORD error;
  2923. switch (Fsm->GetState()) {
  2924. case FSM_STATE_INIT:
  2925. error = pSocket->Receive_Start(stateMachine);
  2926. break;
  2927. case FSM_STATE_CONTINUE:
  2928. case FSM_STATE_ERROR:
  2929. error = pSocket->Receive_Continue(stateMachine);
  2930. break;
  2931. default:
  2932. error = ERROR_WINHTTP_INTERNAL_ERROR;
  2933. Fsm->SetDone(ERROR_WINHTTP_INTERNAL_ERROR);
  2934. INET_ASSERT(FALSE);
  2935. break;
  2936. }
  2937. DEBUG_LEAVE(error);
  2938. return error;
  2939. }
  2940. DWORD
  2941. ICSocket::Receive_Start(
  2942. IN CFsm_SocketReceive * Fsm
  2943. )
  2944. /*++
  2945. Routine Description:
  2946. Initiates a receive request - grows the buffer if required and kicks off the
  2947. first receive operation
  2948. Arguments:
  2949. Fsm - reference to FSM controlling operation
  2950. Return Value:
  2951. DWORD
  2952. Success - ERROR_SUCCESS
  2953. ERROR_IO_PENDING
  2954. Operation will complete asynchronously
  2955. Failure -
  2956. --*/
  2957. {
  2958. DEBUG_ENTER((DBG_SOCKETS,
  2959. Dword,
  2960. "ICSocket::Receive_Start",
  2961. "{%#x [%#x/%d]} %#x(%#x [%#x], %#x [%d], %#x [%d], %#x [%d], %d, %#x, %#x [%B])",
  2962. this,
  2963. GetSocket(),
  2964. GetSourcePort(),
  2965. Fsm,
  2966. Fsm->m_lplpBuffer,
  2967. *Fsm->m_lplpBuffer,
  2968. Fsm->m_lpdwBufferLength,
  2969. *Fsm->m_lpdwBufferLength,
  2970. Fsm->m_lpdwBufferRemaining,
  2971. *Fsm->m_lpdwBufferRemaining,
  2972. Fsm->m_lpdwBytesReceived,
  2973. *Fsm->m_lpdwBytesReceived,
  2974. Fsm->m_dwExtraSpace,
  2975. Fsm->m_dwFlags,
  2976. Fsm->m_lpbEof,
  2977. *Fsm->m_lpbEof
  2978. ));
  2979. CFsm_SocketReceive & fsm = *Fsm;
  2980. DWORD error = ERROR_SUCCESS;
  2981. //
  2982. // if we weren't given a buffer, but the caller told us its okay to resize
  2983. // then we allocate the initial buffer
  2984. //
  2985. if ((fsm.m_dwBufferLength == 0) || (fsm.m_dwBufferLeft == 0)) {
  2986. INET_ASSERT((fsm.m_dwBufferLength == 0) ? (fsm.m_dwBufferLeft == 0) : TRUE);
  2987. if (fsm.m_dwFlags & SF_EXPAND) {
  2988. //
  2989. // allocate a fixed memory buffer
  2990. //
  2991. //
  2992. // BUGBUG - the initial buffer size should come from the handle
  2993. // object
  2994. //
  2995. fsm.m_dwBufferLeft = DEFAULT_RECEIVE_BUFFER_INCREMENT;
  2996. if (fsm.m_dwBufferLength == 0) {
  2997. fsm.m_bAllocated = TRUE;
  2998. }
  2999. fsm.m_dwBufferLength += fsm.m_dwBufferLeft;
  3000. DEBUG_PRINT(SOCKETS,
  3001. INFO,
  3002. ("resizing %#x to %d\n",
  3003. fsm.m_hBuffer,
  3004. fsm.m_dwBufferLength
  3005. ));
  3006. fsm.m_hBuffer = ResizeBuffer(fsm.m_hBuffer, fsm.m_dwBufferLength, FALSE);
  3007. if (fsm.m_hBuffer == (HLOCAL)NULL) {
  3008. error = GetLastError();
  3009. INET_ASSERT(error != ERROR_SUCCESS);
  3010. fsm.m_bAllocated = FALSE;
  3011. }
  3012. } else {
  3013. //
  3014. // the caller didn't say its okay to resize
  3015. //
  3016. error = ERROR_INSUFFICIENT_BUFFER;
  3017. }
  3018. } else if (fsm.m_hBuffer == (HLOCAL)NULL) {
  3019. error = ERROR_INSUFFICIENT_BUFFER;
  3020. }
  3021. if (error == ERROR_SUCCESS) {
  3022. if (fsm.GetMappedHandleObject() != NULL) {
  3023. fsm.GetMappedHandleObject()->SetAbortHandle(this);
  3024. }
  3025. //
  3026. // keep the app informed (if requested to do so)
  3027. //
  3028. if (fsm.m_dwFlags & SF_INDICATE) {
  3029. error = InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0);
  3030. if (error != ERROR_SUCCESS)
  3031. {
  3032. INET_ASSERT(error == ERROR_WINHTTP_OPERATION_CANCELLED);
  3033. fsm.SetError(error);
  3034. }
  3035. }
  3036. //
  3037. // kick off the receive request. If we complete synchronously (with
  3038. // an error or successfully), then call the finish handler here
  3039. //
  3040. error = Receive_Continue(Fsm);
  3041. } else {
  3042. fsm.SetDone();
  3043. }
  3044. DEBUG_LEAVE(error);
  3045. return error;
  3046. }
  3047. DWORD
  3048. ICSocket::Receive_Continue(
  3049. IN CFsm_SocketReceive * Fsm
  3050. )
  3051. /*++
  3052. Routine Description:
  3053. Receives data from connected socket. Depending on flags settings, we will
  3054. perform a single receive, loop until we have filled the buffer and/or loop
  3055. until we have received all the data.
  3056. Arguments:
  3057. Fsm - reference to FSM controlling operation
  3058. Return Value:
  3059. DWORD
  3060. Success - ERROR_SUCCESS
  3061. ERROR_IO_PENDING
  3062. Operation will complete asynchronously
  3063. Failure -
  3064. --*/
  3065. {
  3066. DEBUG_ENTER((DBG_SOCKETS,
  3067. Dword,
  3068. "ICSocket::Receive_Continue",
  3069. "{%#x [%#x/%d]} %#x(%#x [%#x], %#x [%d], %#x [%d], %#x [%d], %d, %#x, %#x [%B])",
  3070. this,
  3071. GetSocket(),
  3072. GetSourcePort(),
  3073. Fsm,
  3074. Fsm->m_lplpBuffer,
  3075. *Fsm->m_lplpBuffer,
  3076. Fsm->m_lpdwBufferLength,
  3077. *Fsm->m_lpdwBufferLength,
  3078. Fsm->m_lpdwBufferRemaining,
  3079. *Fsm->m_lpdwBufferRemaining,
  3080. Fsm->m_lpdwBytesReceived,
  3081. *Fsm->m_lpdwBytesReceived,
  3082. Fsm->m_dwExtraSpace,
  3083. Fsm->m_dwFlags,
  3084. Fsm->m_lpbEof,
  3085. *Fsm->m_lpbEof
  3086. ));
  3087. CFsm_SocketReceive & fsm = *Fsm;
  3088. DWORD error = fsm.GetError();
  3089. INTERNET_HANDLE_OBJECT * pObject = fsm.GetMappedHandleObject();
  3090. if (error != ERROR_SUCCESS) {
  3091. goto error_exit;
  3092. }
  3093. fsm.m_lpBuffer = (LPBYTE)fsm.m_hBuffer + fsm.m_dwBytesReceived;
  3094. //
  3095. // receive some data
  3096. //
  3097. do
  3098. {
  3099. if (fsm.m_pServerInfo != NULL)
  3100. {
  3101. fsm.m_pServerInfo->SetLastActiveTime();
  3102. }
  3103. INET_ASSERT((int)fsm.m_dwBufferLeft > 0);
  3104. int nRead;
  3105. if (IsNonBlocking())
  3106. {
  3107. if (fsm.bIOCPInited)
  3108. {
  3109. fsm.bIOCPInited = FALSE;
  3110. nRead = fsm.dwBytesTransferred;
  3111. if (fsm.bIOCPSuccess)
  3112. {
  3113. RecvSucceeded:
  3114. if (nRead == 0)
  3115. {
  3116. //
  3117. // done
  3118. //
  3119. DEBUG_PRINT(SOCKETS,
  3120. INFO,
  3121. ("EOF connection %#x/port %d\n",
  3122. m_Socket,
  3123. m_SourcePort
  3124. ));
  3125. fsm.m_bEof = TRUE;
  3126. break;
  3127. }
  3128. else if (nRead > 0)
  3129. {
  3130. DEBUG_PRINT(SOCKETS,
  3131. INFO,
  3132. ("received %d bytes from socket %#x/port %d\n",
  3133. nRead,
  3134. m_Socket,
  3135. m_SourcePort
  3136. ));
  3137. fsm.m_dwBytesReceived += nRead;
  3138. fsm.m_dwBytesRead += nRead;
  3139. fsm.m_lpBuffer += nRead;
  3140. fsm.m_dwBufferLeft -= nRead;
  3141. //
  3142. // if SF_RECEIVE_ALL is not set then the caller just wants us to
  3143. // perform a single receive. We're done
  3144. //
  3145. if (!(fsm.m_dwFlags & SF_RECEIVE_ALL) )
  3146. {
  3147. break;
  3148. }
  3149. //
  3150. // if we've filled the current buffer, then either we're done, or
  3151. // the caller wants us to receive the entire response, in which
  3152. // case we attempt to grow the buffer and receive the next part
  3153. // of the message. Note that we may have already received the
  3154. // entire response if it just happened to be the same size as our
  3155. // buffer
  3156. //
  3157. // BUGBUG [arthurbi] we're broken for SSL/PCT case !!!
  3158. // We need to handle expanding the buffer.
  3159. //
  3160. if (fsm.m_dwBufferLeft == 0)
  3161. {
  3162. //
  3163. // BUGBUG - RLF - why are we testing for SF_DECRYPT here?
  3164. //
  3165. if (!(fsm.m_dwFlags & SF_EXPAND) || (m_dwFlags & SF_DECRYPT))
  3166. {
  3167. break;
  3168. }
  3169. else
  3170. {
  3171. //
  3172. // BUGBUG - the buffer increment should come from the handle
  3173. // object
  3174. //
  3175. fsm.m_dwBufferLeft = DEFAULT_RECEIVE_BUFFER_INCREMENT;
  3176. fsm.m_dwBufferLength += DEFAULT_RECEIVE_BUFFER_INCREMENT;
  3177. DEBUG_PRINT(SOCKETS,
  3178. INFO,
  3179. ("resizing %#x to %d\n",
  3180. fsm.m_hBuffer,
  3181. fsm.m_dwBufferLength
  3182. ));
  3183. fsm.m_hBuffer = ResizeBuffer(fsm.m_hBuffer,
  3184. fsm.m_dwBufferLength,
  3185. FALSE
  3186. );
  3187. if (fsm.m_hBuffer != NULL)
  3188. {
  3189. fsm.m_lpBuffer = (LPBYTE)fsm.m_hBuffer + fsm.m_dwBytesReceived;
  3190. }
  3191. else
  3192. {
  3193. error = GetLastError();
  3194. INET_ASSERT(error != ERROR_SUCCESS);
  3195. fsm.m_dwBytesReceived = 0;
  3196. fsm.m_dwBufferLength = 0;
  3197. fsm.m_dwBufferLeft = 0;
  3198. }
  3199. }
  3200. }// if fsm.m_dwBufferLeft == 0
  3201. }// if nRead >= 0
  3202. }// if fsm.bIOCPSuccess
  3203. else
  3204. {
  3205. error = fsm.dwIOCPError;
  3206. // a real error occurred. We need to get out
  3207. //
  3208. error = MapInternetError(error);
  3209. //VENKATKBUG_ remove this assert later - only informational
  3210. //informational INET_ASSERT (FALSE && "IOCPError");
  3211. break;
  3212. }// if! fsm.bSuccess
  3213. continue; //for any fall-thrus.
  3214. } // if fsm.bIOCPInited
  3215. int nError;
  3216. WSABUF wsabuf;
  3217. wsabuf.len = fsm.m_dwBufferLeft;
  3218. wsabuf.buf = (char FAR *)fsm.m_lpBuffer;
  3219. DWORD dwFlags = 0;
  3220. //
  3221. // First try Winsock Fast I/O: see if Winsock can
  3222. // satisfy the recv call immediately. If it fails,
  3223. // we assume the error is WSAWOULDBLOCK and then
  3224. // try WSARecv again with the lpOverlapped parameter.
  3225. //
  3226. nError = _I_WSARecv(m_Socket,
  3227. &wsabuf,
  3228. 1,
  3229. (LPDWORD)&nRead,
  3230. &dwFlags,
  3231. NULL,
  3232. NULL);
  3233. if (nError == 0)
  3234. {
  3235. goto RecvSucceeded;
  3236. }
  3237. //
  3238. // Slow path: issue an async recv call, with the results
  3239. // to be posted to our I/O completion port.
  3240. //
  3241. if (!_lpWrapOverlappedRecv)
  3242. {
  3243. _lpWrapOverlappedRecv = New CWrapOverlapped();
  3244. if (!_lpWrapOverlappedRecv)
  3245. {
  3246. error = ERROR_NOT_ENOUGH_MEMORY;
  3247. fsm.SetErrorState(error);
  3248. goto error_exit;
  3249. }
  3250. }
  3251. CWrapOverlapped* lpWrapOverlapped = _lpWrapOverlappedRecv;
  3252. LPWSAOVERLAPPED lpOverlapped = _lpWrapOverlappedRecv->GetOverlapped();
  3253. memset(lpOverlapped, 0, sizeof(WSAOVERLAPPED));
  3254. CFsm* pFsmOld = GetAndSetCurrentFsm(&fsm);
  3255. UNREFERENCED_PARAMETER(pFsmOld); // eliminate C4701 in free builds
  3256. INET_ASSERT (pFsmOld == NULL);
  3257. fsm.bIOCPInited = TRUE;
  3258. fsm.SetAction(FSM_ACTION_RECEIVE);
  3259. DWORD timeout = GetTimeoutValue(WINHTTP_OPTION_RECEIVE_TIMEOUT);
  3260. if (timeout != INFINITE)
  3261. {
  3262. fsm.SetTimeout(timeout);
  3263. #ifdef USE_OLD_SENDRECV_SYNC
  3264. fsm.SetOnAsyncList(TRUE);
  3265. #else
  3266. //additional reference for timeout queue
  3267. fsm.Reference();
  3268. fsm.SetPop(FALSE);
  3269. #endif
  3270. if (Fsm->GetMappedHandleObject())
  3271. {
  3272. Fsm->GetMappedHandleObject()->Reference();
  3273. }
  3274. error = QueueTimeoutFsm(Fsm, m_Socket);
  3275. if (error != ERROR_IO_PENDING)
  3276. {
  3277. // 2 causes - both irrecoverable
  3278. // 1. no global pointer to ICAsyncThread (impossible)
  3279. // OR 2. no threadinfo or SelectThread or out of memory.
  3280. // so bail!
  3281. fsm.bIOCPInited = FALSE;
  3282. GetAndSetCurrentFsm(NULL);
  3283. #ifdef USE_OLD_SENDRECV_SYNC
  3284. fsm.SetOnAsyncList(FALSE);
  3285. #else
  3286. if (Fsm->GetMappedHandleObject())
  3287. {
  3288. Fsm->GetMappedHandleObject()->Dereference();
  3289. }
  3290. DWORD dwDummy = 0;
  3291. fsm.Dereference(&dwDummy);
  3292. #endif
  3293. fsm.SetErrorState(error);
  3294. goto error_exit;
  3295. }
  3296. }
  3297. _lpWrapOverlappedRecv->Reference(); // to keep this ICSocket=>the Overlapped struct valid beyong the WSARecv() call.
  3298. _lpWrapOverlappedRecv->Reference(); // to make sure it stays alive for the IOCP to get the fsm off it.
  3299. DEBUG_PRINT(SOCKETS,
  3300. INFO,
  3301. ("calling WSARecv() blocked, socket %#x/port %d\n",
  3302. m_Socket,
  3303. m_SourcePort
  3304. ));
  3305. DEBUG_ENTER((DBG_API,
  3306. Dword,
  3307. "***WSARecv",
  3308. "(m_Socket)%#x, (wsabuf.buf)%#x, (wsabuf.len)%#x, (this)%#x, (overlapped)%#x, (fsm)%#x",
  3309. m_Socket,
  3310. wsabuf.buf,
  3311. wsabuf.len,
  3312. this,
  3313. lpOverlapped,
  3314. &fsm
  3315. ));
  3316. nError = _I_WSARecv(m_Socket,
  3317. &wsabuf,
  3318. 1,
  3319. (LPDWORD)&nRead,
  3320. &dwFlags,
  3321. lpOverlapped,
  3322. NULL);
  3323. DEBUG_LEAVE(nError);
  3324. lpWrapOverlapped->Dereference(); // release the first reference.
  3325. DEBUG_PRINT(SOCKETS,
  3326. ERROR,
  3327. ("WSARecv() returns %d (%s) with nRead=%d bytes\n",
  3328. nError,
  3329. InternetMapError(nError),
  3330. nRead
  3331. ));
  3332. //VENKATKBUG - omitting Win95 hackorama (see below sync case.), but may need to put it in just the same.
  3333. if (nError == 0)
  3334. {
  3335. #if INET_DEBUG
  3336. InterlockedIncrement(&g_cWSACompletions);
  3337. #endif
  3338. error = ERROR_IO_PENDING;
  3339. break;
  3340. }
  3341. else // if! nError == 0
  3342. {
  3343. INET_ASSERT (nError == SOCKET_ERROR);
  3344. error = _I_WSAGetLastError();
  3345. if (error == WSA_IO_PENDING)
  3346. {
  3347. #if INET_DEBUG
  3348. InterlockedIncrement(&g_cWSACompletions);
  3349. #endif
  3350. error = ERROR_IO_PENDING;
  3351. break;
  3352. }
  3353. else
  3354. {
  3355. // no IOCompletion here.
  3356. if (fsm.HasTimeout())
  3357. {
  3358. #ifdef USE_OLD_SENDRECV_SYNC
  3359. if (!RemoveFsmFromAsyncList(&fsm))
  3360. {
  3361. //the timeout thread already enforced timeout and updated state
  3362. }
  3363. #else
  3364. if (!fsm.TestAndSetValidForIOCPProcessing())
  3365. {
  3366. //the timeout thread already enforced timeout and updated state
  3367. }
  3368. #endif
  3369. }
  3370. lpWrapOverlapped->Dereference(); // release the IOCP-based reference.
  3371. GetAndSetCurrentFsm(NULL);
  3372. //cannot handle SF_NO_WAIT and SF_WAIT
  3373. error = MapInternetError(error);
  3374. break;
  3375. }
  3376. } // if! nError == 0
  3377. }
  3378. else //if IsNonBlocking()
  3379. {
  3380. nRead = _I_recv(m_Socket,
  3381. (char FAR *)fsm.m_lpBuffer,
  3382. (int)fsm.m_dwBufferLeft,
  3383. 0
  3384. );
  3385. //
  3386. // hackorama # 95, subparagraph 13
  3387. //
  3388. // RLF 07/15/96
  3389. //
  3390. // On Win95 (wouldn't you know it?) in low-memory conditions, we can get
  3391. // into a situation where one or more pages of our receive buffer is
  3392. // filled with zeroes.
  3393. //
  3394. // The reason this happens is that the winsock VxD creates an alias to
  3395. // our buffer, locks the buffer & writes into it, then marks the alias
  3396. // dirty, but not the original buffer. If the buffer is paged out then
  3397. // back in, one or more pages are zeroed because the O/S didn't know
  3398. // they had been written to; it decides to initialize the pages with
  3399. // zeroes.
  3400. //
  3401. // We try to circumvent this by immediately probing each page (we read
  3402. // a byte then write it back).
  3403. //
  3404. // This doesn't fix the problem, just makes the window a lot smaller.
  3405. // However, apart from writing a device driver or modifying the VxD,
  3406. // there's not much else we can do
  3407. //
  3408. ProbeWriteBuffer(fsm.m_lpBuffer, fsm.m_dwBufferLeft);
  3409. if (nRead == 0)
  3410. {
  3411. //
  3412. // done
  3413. //
  3414. DEBUG_PRINT(SOCKETS,
  3415. INFO,
  3416. ("EOF connection %#x/port %d\n",
  3417. m_Socket,
  3418. m_SourcePort
  3419. ));
  3420. fsm.m_bEof = TRUE;
  3421. break;
  3422. }
  3423. else if (nRead > 0)
  3424. {
  3425. DEBUG_PRINT(SOCKETS,
  3426. INFO,
  3427. ("received %d bytes from socket %#x/port %d\n",
  3428. nRead,
  3429. m_Socket,
  3430. m_SourcePort
  3431. ));
  3432. fsm.m_dwBytesReceived += nRead;
  3433. fsm.m_dwBytesRead += nRead;
  3434. fsm.m_lpBuffer += nRead;
  3435. fsm.m_dwBufferLeft -= nRead;
  3436. //
  3437. // if SF_RECEIVE_ALL is not set then the caller just wants us to
  3438. // perform a single receive. We're done
  3439. //
  3440. if (!(fsm.m_dwFlags & SF_RECEIVE_ALL) )
  3441. {
  3442. break;
  3443. }
  3444. //
  3445. // if we've filled the current buffer, then either we're done, or
  3446. // the caller wants us to receive the entire response, in which
  3447. // case we attempt to grow the buffer and receive the next part
  3448. // of the message. Note that we may have already received the
  3449. // entire response if it just happened to be the same size as our
  3450. // buffer
  3451. //
  3452. // BUGBUG [arthurbi] we're broken for SSL/PCT case !!!
  3453. // We need to handle expanding the buffer.
  3454. //
  3455. if (fsm.m_dwBufferLeft == 0)
  3456. {
  3457. //
  3458. // BUGBUG - RLF - why are we testing for SF_DECRYPT here?
  3459. //
  3460. if (!(fsm.m_dwFlags & SF_EXPAND) || (m_dwFlags & SF_DECRYPT))
  3461. {
  3462. break;
  3463. }
  3464. else
  3465. {
  3466. //
  3467. // BUGBUG - the buffer increment should come from the handle
  3468. // object
  3469. //
  3470. fsm.m_dwBufferLeft = DEFAULT_RECEIVE_BUFFER_INCREMENT;
  3471. fsm.m_dwBufferLength += DEFAULT_RECEIVE_BUFFER_INCREMENT;
  3472. DEBUG_PRINT(SOCKETS,
  3473. INFO,
  3474. ("resizing %#x to %d\n",
  3475. fsm.m_hBuffer,
  3476. fsm.m_dwBufferLength
  3477. ));
  3478. fsm.m_hBuffer = ResizeBuffer(fsm.m_hBuffer,
  3479. fsm.m_dwBufferLength,
  3480. FALSE
  3481. );
  3482. if (fsm.m_hBuffer != NULL)
  3483. {
  3484. fsm.m_lpBuffer = (LPBYTE)fsm.m_hBuffer + fsm.m_dwBytesReceived;
  3485. }
  3486. else
  3487. {
  3488. error = GetLastError();
  3489. INET_ASSERT(error != ERROR_SUCCESS);
  3490. fsm.m_dwBytesReceived = 0;
  3491. fsm.m_dwBufferLength = 0;
  3492. fsm.m_dwBufferLeft = 0;
  3493. }
  3494. }
  3495. }//if fsm.m_dwBufferLeft == 0
  3496. }
  3497. else //if nRead >= 0
  3498. {
  3499. if (IsAborted())
  3500. {
  3501. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  3502. break;
  3503. }
  3504. else
  3505. {
  3506. error = _I_WSAGetLastError();
  3507. //
  3508. // a real error occurred. We need to get out
  3509. //
  3510. DEBUG_PRINT(SOCKETS,
  3511. ERROR,
  3512. ("recv() on socket %#x/port %d returns %d\n",
  3513. m_Socket,
  3514. m_SourcePort,
  3515. error
  3516. ));
  3517. error = MapInternetError(error);
  3518. break;
  3519. }
  3520. }//if! nRead >= 0
  3521. }// if! IsNonBlocking()
  3522. }
  3523. while (error == ERROR_SUCCESS);
  3524. error_exit:
  3525. //
  3526. // get correct error based on settings
  3527. //
  3528. if (error == ERROR_IO_PENDING)
  3529. {
  3530. goto done;
  3531. }
  3532. else if (IsAborted())
  3533. {
  3534. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  3535. }
  3536. if (pObject != NULL) {
  3537. pObject->ResetAbortHandle();
  3538. }
  3539. if (error == ERROR_SUCCESS) {
  3540. //
  3541. // inform the app that we finished, and tell it how much we received
  3542. // this time
  3543. //
  3544. if (fsm.m_dwFlags & SF_INDICATE) {
  3545. DWORD dwBytesRead = fsm.m_dwBytesRead;
  3546. InternetIndicateStatus(WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED,
  3547. &dwBytesRead,
  3548. sizeof(dwBytesRead)
  3549. );
  3550. }
  3551. //
  3552. // if we received the entire response and the caller specified
  3553. // SF_COMPRESS then we shrink the buffer to fit. We may end up growing
  3554. // the buffer to contain dwExtraSpace if it is not zero and we just
  3555. // happened to fill the current buffer
  3556. //
  3557. if (fsm.m_bEof && (fsm.m_dwFlags & SF_COMPRESS)) {
  3558. fsm.m_dwBufferLeft = fsm.m_dwExtraSpace;
  3559. //
  3560. // include any extra that the caller required
  3561. //
  3562. fsm.m_dwBufferLength = fsm.m_dwBytesReceived + fsm.m_dwExtraSpace;
  3563. DEBUG_PRINT(SOCKETS,
  3564. INFO,
  3565. ("shrinking buffer %#x to %d (%#x) bytes (includes %d extra)\n",
  3566. fsm.m_hBuffer,
  3567. fsm.m_dwBufferLength,
  3568. fsm.m_dwBufferLength,
  3569. fsm.m_dwExtraSpace
  3570. ));
  3571. fsm.m_hBuffer = ResizeBuffer(fsm.m_hBuffer,
  3572. fsm.m_dwBufferLength,
  3573. FALSE
  3574. );
  3575. INET_ASSERT((fsm.m_hBuffer == NULL)
  3576. ? ((fsm.m_dwBytesReceived + fsm.m_dwExtraSpace) == 0)
  3577. : TRUE
  3578. );
  3579. }
  3580. DEBUG_PRINT(SOCKETS,
  3581. INFO,
  3582. ("read %d bytes @ %#x from socket %#x/port %d\n",
  3583. fsm.m_dwBytesRead,
  3584. (LPBYTE)fsm.m_hBuffer + *fsm.m_lpdwBytesReceived,
  3585. m_Socket,
  3586. m_SourcePort
  3587. ));
  3588. DEBUG_DUMP_API(SOCKETS,
  3589. "received data:\n",
  3590. (LPBYTE)fsm.m_hBuffer + *fsm.m_lpdwBytesReceived,
  3591. fsm.m_dwBytesRead
  3592. );
  3593. TRACE_DUMP_API_IF_REQUEST(SOCKETS,
  3594. "received data:\n",
  3595. (LPBYTE)fsm.m_hBuffer + *fsm.m_lpdwBytesReceived,
  3596. fsm.m_dwBytesRead,
  3597. (HANDLE_OBJECT *)(fsm.GetMappedHandle())
  3598. );
  3599. } else if (fsm.m_bAllocated && (fsm.m_hBuffer != NULL)) {
  3600. //
  3601. // if we failed but allocated a buffer then we need to free it (we were
  3602. // leaking this buffer if the request was cancelled)
  3603. //
  3604. fsm.m_hBuffer = FREE_MEMORY(fsm.m_hBuffer);
  3605. INET_ASSERT(fsm.m_hBuffer == NULL);
  3606. fsm.m_dwBufferLength = 0;
  3607. fsm.m_dwBufferLeft = 0;
  3608. fsm.m_dwBytesReceived = 0;
  3609. fsm.m_bEof = TRUE;
  3610. }
  3611. DEBUG_PRINT(SOCKETS,
  3612. INFO,
  3613. ("returning: lpBuffer=%#x, bufferLength=%d, bufferLeft=%d, bytesReceived=%d\n",
  3614. fsm.m_hBuffer,
  3615. fsm.m_dwBufferLength,
  3616. fsm.m_dwBufferLeft,
  3617. fsm.m_dwBytesReceived
  3618. ));
  3619. //
  3620. // update output parameters
  3621. //
  3622. *fsm.m_lplpBuffer = (LPVOID)fsm.m_hBuffer;
  3623. *fsm.m_lpdwBufferLength = fsm.m_dwBufferLength;
  3624. *fsm.m_lpdwBufferRemaining = fsm.m_dwBufferLeft;
  3625. *fsm.m_lpdwBytesReceived = fsm.m_dwBytesReceived;
  3626. *fsm.m_lpbEof = fsm.m_bEof;
  3627. if (error != ERROR_IO_PENDING) {
  3628. fsm.SetDone(error);
  3629. }
  3630. done:
  3631. DEBUG_LEAVE(error);
  3632. return error;
  3633. }
  3634. //
  3635. //DWORD
  3636. //ICSocket::ReceiveFrom(
  3637. // IN LPVOID lpBuffer,
  3638. // IN DWORD dwBufferLength,
  3639. // OUT LPDWORD lpdwBytesReceived,
  3640. // OUT LPSOCKADDR lpDestination OPTIONAL,
  3641. // IN OUT LPDWORD lpdwDestinationLength OPTIONAL,
  3642. // IN DWORD dwTimeout,
  3643. // IN DWORD dwWinsockFlags,
  3644. // IN DWORD dwFlags
  3645. // )
  3646. //
  3647. ///*++
  3648. //
  3649. //Routine Description:
  3650. //
  3651. // Wrapper for recvfrom()
  3652. //
  3653. //Arguments:
  3654. //
  3655. // lpBuffer - pointer to buffer where data returned
  3656. //
  3657. // dwBufferLength - size of lpBuffer in bytes
  3658. //
  3659. // lpdwBytesReceived - pointer to returned number of bytes received
  3660. //
  3661. // lpDestination - pointer to returned destination address
  3662. //
  3663. // lpdwDestinationLength - IN: size of lpDestination buffer
  3664. // OUT: length of returned destination address info
  3665. //
  3666. // dwTimeout - number of milliseconds to wait for response
  3667. //
  3668. // dwWinsockFlags - flags to pass through to recvfrom()
  3669. //
  3670. // dwFlags - ICSocket flags
  3671. //
  3672. //Return Value:
  3673. //
  3674. // DWORD
  3675. // Success - ERROR_SUCCESS
  3676. //
  3677. // Failure - ERROR_WINHTTP_OPERATION_CANCELLED
  3678. // The operation was cancelled by the caller
  3679. //
  3680. // ERROR_WINHTTP_TIMEOUT
  3681. // The operation timed out
  3682. //
  3683. // ERROR_WINHTTP_CONNECTION_ERROR
  3684. // An error occurred. We approximate to connection reset
  3685. //
  3686. // WSA error
  3687. // Some other sockets error occurred
  3688. //
  3689. //--*/
  3690. //
  3691. //{
  3692. // DEBUG_ENTER((DBG_SOCKETS,
  3693. // Dword,
  3694. // "ICSocket::ReceiveFrom",
  3695. // "{%#x} %#x, %d, %#x, %#x, %#x [%d], %d, %#x, %#x",
  3696. // m_Socket,
  3697. // lpBuffer,
  3698. // dwBufferLength,
  3699. // lpdwBytesReceived,
  3700. // lpDestination,
  3701. // lpdwDestinationLength,
  3702. // lpdwDestinationLength ? *lpdwDestinationLength : 0,
  3703. // dwTimeout,
  3704. // dwWinsockFlags,
  3705. // dwFlags
  3706. // ));
  3707. //
  3708. // //INET_ASSERT(IsSocketValid());
  3709. // INET_ASSERT(lpdwBytesReceived != NULL);
  3710. //
  3711. // //
  3712. // // most ICSocket flags not allowed for this operation
  3713. // //
  3714. //
  3715. // INET_ASSERT(!(dwFlags
  3716. // & (SF_ENCRYPT
  3717. // | SF_DECRYPT
  3718. // | SF_EXPAND
  3719. // | SF_COMPRESS
  3720. // | SF_SENDING_DATA
  3721. // | SF_SCH_REDO
  3722. // )
  3723. // )
  3724. // );
  3725. //
  3726. // DWORD error = ERROR_SUCCESS;
  3727. // LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  3728. // BOOL bStopOfflineTimer = FALSE;
  3729. // BOOL fNonBlocking;
  3730. // DWORD bytesReceived;
  3731. // INTERNET_HANDLE_OBJECT * pObject = NULL;
  3732. //
  3733. // if (lpThreadInfo == NULL) {
  3734. //
  3735. // INET_ASSERT(FALSE);
  3736. //
  3737. // error = ERROR_WINHTTP_INTERNAL_ERROR;
  3738. // goto quit;
  3739. // }
  3740. //
  3741. // //
  3742. // // the socket may have already been aborted
  3743. // //
  3744. //
  3745. // if (IsAborted()) {
  3746. // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  3747. // goto quit;
  3748. // }
  3749. //
  3750. // //
  3751. // // let another thread know the socket to cancel if it wants to kill this
  3752. // // operation
  3753. // //
  3754. //
  3755. // pObject = (INTERNET_HANDLE_OBJECT * )lpThreadInfo->hObjectMapped;
  3756. // if (pObject != NULL) {
  3757. // pObject->SetAbortHandle(this);
  3758. // }
  3759. //
  3760. // //
  3761. // // keep the app informed (if requested to do so)
  3762. // //
  3763. //
  3764. // if (dwFlags & SF_INDICATE) {
  3765. // InternetIndicateStatus(INTERNET_STATUS_RECEIVING_RESPONSE,
  3766. // NULL,
  3767. // 0
  3768. // );
  3769. // }
  3770. //
  3771. // //
  3772. // // if we are in async (== non-blocking) mode, let the async request
  3773. // // scheduler know what operation we will be waiting on
  3774. // //
  3775. //
  3776. // fNonBlocking = lpThreadInfo->IsAsyncWorkerThread;
  3777. // if (fNonBlocking) {
  3778. //
  3779. // INET_ASSERT(lpThreadInfo->lpArb != NULL);
  3780. //
  3781. // SET_ARB_SOCKET_OPERATION_TIMEOUT(lpThreadInfo->lpArb,
  3782. // m_Socket,
  3783. // RECEIVE,
  3784. // dwTimeout
  3785. // );
  3786. //
  3787. // DWORD timerError = StartOfflineTimerForArb(lpThreadInfo->lpArb);
  3788. //
  3789. // INET_ASSERT(timerError == ERROR_SUCCESS);
  3790. //
  3791. // bStopOfflineTimer = (timerError == ERROR_SUCCESS) ? TRUE : FALSE;
  3792. // }
  3793. //
  3794. // int nBytes;
  3795. //
  3796. // bytesReceived = 0;
  3797. //
  3798. // do {
  3799. //
  3800. // nBytes = _I_recvfrom(m_Socket,
  3801. // (char FAR *)lpBuffer + bytesReceived,
  3802. // dwBufferLength,
  3803. // dwWinsockFlags,
  3804. // lpDestination,
  3805. // (int FAR *)lpdwDestinationLength
  3806. // );
  3807. // if (nBytes != SOCKET_ERROR) {
  3808. //
  3809. // DEBUG_PRINT(SOCKETS,
  3810. // INFO,
  3811. // ("received %d bytes from socket %#x\n",
  3812. // nBytes,
  3813. // m_Socket
  3814. // ));
  3815. //
  3816. // INET_ASSERT(nBytes > 0);
  3817. //
  3818. // bytesReceived += nBytes;
  3819. // dwBufferLength -= nBytes;
  3820. //
  3821. // //
  3822. // // for recvfrom(), we quit as soon as we get some data
  3823. // //
  3824. //
  3825. // error = ERROR_SUCCESS;
  3826. // break;
  3827. // } else {
  3828. // error = _I_WSAGetLastError();
  3829. // if ((error == WSAEWOULDBLOCK) && fNonBlocking) {
  3830. //
  3831. // INET_ASSERT(_dwFlags & SF_NON_BLOCKING);
  3832. //
  3833. // //
  3834. // // if this function is called expedited (we expect the request
  3835. // // to complete quickly) then we test to see if it already
  3836. // // completed before switching to the async scheduler
  3837. // //
  3838. //
  3839. // BOOL switchFiber = TRUE;
  3840. //
  3841. // if (dwFlags & SF_EXPEDITED) {
  3842. // error = WaitForReceive(1);
  3843. //
  3844. // //
  3845. // // if the socket is already readable then we don't switch
  3846. // // fibers (only to virtually immediately come back here,
  3847. // // incurring a couple of thread switches
  3848. // //
  3849. //
  3850. // if (error == ERROR_SUCCESS) {
  3851. // switchFiber = FALSE;
  3852. //
  3853. // //
  3854. // // use this error to go round loop once again
  3855. // //
  3856. //
  3857. // error = WSAEWOULDBLOCK;
  3858. // }
  3859. // }
  3860. // if (switchFiber) {
  3861. //
  3862. // DEBUG_PRINT(SOCKETS,
  3863. // INFO,
  3864. // ("recvfrom(%#x) blocked\n",
  3865. // m_Socket
  3866. // ));
  3867. //
  3868. // lpThreadInfo->lpArb->Header.dwResultCode = ERROR_SUCCESS;
  3869. //
  3870. // SwitchToAsyncScheduler(m_Socket);
  3871. //
  3872. // error = lpThreadInfo->lpArb->Header.dwResultCode;
  3873. //
  3874. // DEBUG_PRINT(SOCKETS,
  3875. // INFO,
  3876. // ("recvfrom(%#x) resumed, returns %s\n",
  3877. // m_Socket,
  3878. // InternetMapError(error)
  3879. // ));
  3880. //
  3881. // if (error != ERROR_SUCCESS) {
  3882. // } else {
  3883. //
  3884. // //
  3885. // // use this error to force another loop now we believe
  3886. // // we have the data
  3887. // //
  3888. //
  3889. // error = WSAEWOULDBLOCK;
  3890. // }
  3891. // }
  3892. // } else {
  3893. //
  3894. // //
  3895. // // real error
  3896. // //
  3897. //
  3898. // error = MapInternetError(error);
  3899. // }
  3900. // }
  3901. // } while (error == WSAEWOULDBLOCK);
  3902. //
  3903. // if (error == ERROR_SUCCESS) {
  3904. //
  3905. // DEBUG_DUMP(SOCKETS,
  3906. // "received data:\n",
  3907. // lpBuffer,
  3908. // bytesReceived
  3909. // );
  3910. //
  3911. // }
  3912. //
  3913. // if (fNonBlocking) {
  3914. //
  3915. // INET_ASSERT(lpThreadInfo->lpArb != NULL);
  3916. //
  3917. // SET_ARB_SOCKET_OPERATION(lpThreadInfo->lpArb, INVALID_SOCKET, RECEIVE);
  3918. //
  3919. // if (bStopOfflineTimer) {
  3920. // StopOfflineTimerForArb(lpThreadInfo->lpArb);
  3921. // }
  3922. // }
  3923. //
  3924. // //
  3925. // // inform the app that we finished, and tell it how much we received this
  3926. // // time
  3927. // //
  3928. //
  3929. // if ((dwFlags & SF_INDICATE) && (error == ERROR_SUCCESS)) {
  3930. // InternetIndicateStatus(INTERNET_STATUS_RESPONSE_RECEIVED,
  3931. // &bytesReceived,
  3932. // sizeof(bytesReceived)
  3933. // );
  3934. // }
  3935. //
  3936. // *lpdwBytesReceived = bytesReceived;
  3937. //
  3938. // if (pObject != NULL) {
  3939. // pObject->ResetAbortHandle();
  3940. //
  3941. // //
  3942. // // if the operation has been cancelled, then this error overrides any
  3943. // // other
  3944. // //
  3945. //
  3946. // //if (pObject->IsInvalidated()) {
  3947. // // error = pObject->GetError();
  3948. // // if (error == ERROR_SUCCESS) {
  3949. // // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  3950. // // }
  3951. // //}
  3952. // if (IsAborted()) {
  3953. // error = ERROR_WINHTTP_OPERATION_CANCELLED;
  3954. // }
  3955. // }
  3956. //
  3957. //quit:
  3958. //
  3959. // INET_ASSERT((pObject != NULL) ? (pObject->GetAbortHandle() == NULL) : TRUE);
  3960. //
  3961. // DEBUG_LEAVE(error);
  3962. //
  3963. // return error;
  3964. //}
  3965. //
  3966. DWORD
  3967. ICSocket::DataAvailable(
  3968. OUT LPDWORD lpdwBytesAvailable
  3969. )
  3970. /*++
  3971. Routine Description:
  3972. Determines the amount of data available to be read on the socket
  3973. Arguments:
  3974. lpdwBytesAvailable - pointer to returned data available
  3975. Return Value:
  3976. DWORD
  3977. Success - ERROR_SUCCESS
  3978. Failure - WSA error
  3979. --*/
  3980. {
  3981. DEBUG_ENTER((DBG_SOCKETS,
  3982. Dword,
  3983. "ICSocket::DataAvailable",
  3984. "%#x",
  3985. lpdwBytesAvailable
  3986. ));
  3987. //
  3988. // sanity check parameters
  3989. //
  3990. INET_ASSERT(m_Socket != INVALID_SOCKET);
  3991. INET_ASSERT(lpdwBytesAvailable != NULL);
  3992. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  3993. DWORD error;
  3994. if (lpThreadInfo == NULL) {
  3995. //informational INET_ASSERT(FALSE);
  3996. error = ERROR_WINHTTP_INTERNAL_ERROR;
  3997. goto quit;
  3998. }
  3999. //
  4000. // the socket may already be aborted
  4001. //
  4002. if (IsAborted()) {
  4003. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  4004. goto quit;
  4005. }
  4006. //
  4007. // if we're in async mode, we have to perform a zero-length receive in order
  4008. // to get the information from the socket
  4009. //
  4010. int nRead;
  4011. //
  4012. // we actually have to peek a non-zero number of bytes because on Win95,
  4013. // attempting to perform a receive of 0 bytes (to put the socket in blocked
  4014. // read mode) results in zero bytes being returned, and the socket never
  4015. // blocks
  4016. //
  4017. nRead = _I_recv(m_Socket, NULL, 0, 0);
  4018. //
  4019. // N.B. buf[] will only ever be used if there is data to peek right now
  4020. //
  4021. char buf[1];
  4022. PERF_LOG(PE_PEEK_RECEIVE_START,
  4023. m_Socket,
  4024. lpThreadInfo->ThreadId,
  4025. lpThreadInfo->hObject
  4026. );
  4027. nRead = _I_recv(m_Socket, buf, sizeof(buf), MSG_PEEK);
  4028. if (nRead == SOCKET_ERROR) {
  4029. error = _I_WSAGetLastError();
  4030. if ((error == WSAEWOULDBLOCK) && (m_dwFlags & SF_NON_BLOCKING)) {
  4031. DEBUG_PRINT(SOCKETS,
  4032. INFO,
  4033. ("peek(1) blocked, socket %#x\n",
  4034. m_Socket
  4035. ));
  4036. PERF_LOG(PE_PEEK_RECEIVE_END,
  4037. m_Socket,
  4038. lpThreadInfo->ThreadId,
  4039. lpThreadInfo->hObject
  4040. );
  4041. DEBUG_PRINT(SOCKETS,
  4042. INFO,
  4043. ("peek(1) resumed, socket %#x, returns %s\n",
  4044. m_Socket,
  4045. InternetMapError(error)
  4046. ));
  4047. }
  4048. /*} else if ((nRead == 0) && !(m_dwFlags & SF_NON_BLOCKING)) {
  4049. PERF_LOG(PE_PEEK_RECEIVE_END,
  4050. m_Socket,
  4051. lpThreadInfo->ThreadId,
  4052. lpThreadInfo->hObject
  4053. );
  4054. //
  4055. // nothing to peek right now. If the socket is in blocking mode then
  4056. // we wait here until there is something to receive
  4057. //
  4058. error = WaitForReceive(INFINITE);*/
  4059. } else {
  4060. PERF_LOG(PE_PEEK_RECEIVE_END,
  4061. m_Socket,
  4062. lpThreadInfo->ThreadId,
  4063. lpThreadInfo->hObject
  4064. );
  4065. //
  4066. // nRead == 0 but non-blocking, or nRead > 0
  4067. //
  4068. DEBUG_PRINT(SOCKETS,
  4069. INFO,
  4070. ("peek(1) returns %d\n",
  4071. nRead
  4072. ));
  4073. error = ERROR_SUCCESS;
  4074. }
  4075. if (error == ERROR_SUCCESS) {
  4076. //
  4077. // now we can get the amount from the socket
  4078. //
  4079. error = (DWORD)_I_ioctlsocket(m_Socket,
  4080. FIONREAD,
  4081. (u_long FAR *)lpdwBytesAvailable
  4082. );
  4083. //
  4084. // N.B. assumes ioctlsocket() returns 0 on success == ERROR_SUCCESS
  4085. //
  4086. if (error == SOCKET_ERROR) {
  4087. error = _I_WSAGetLastError();
  4088. } else {
  4089. DEBUG_PRINT(SOCKETS,
  4090. INFO,
  4091. ("ioctlsocket(FIONREAD) returns %d\n",
  4092. *lpdwBytesAvailable
  4093. ));
  4094. }
  4095. }
  4096. //
  4097. // map any sockets error to WinHttp error
  4098. //
  4099. if (error != ERROR_SUCCESS) {
  4100. error = MapInternetError(error);
  4101. }
  4102. quit:
  4103. DEBUG_LEAVE(error);
  4104. return error;
  4105. }
  4106. //
  4107. //DWORD
  4108. //ICSocket::DataAvailable2(
  4109. // OUT LPVOID lpBuffer,
  4110. // IN DWORD dwBufferLength,
  4111. // OUT LPDWORD lpdwBytesAvailable
  4112. // )
  4113. //
  4114. ///*++
  4115. //
  4116. //Routine Description:
  4117. //
  4118. // Determines the amount of data available to be read on the socket
  4119. //
  4120. //Arguments:
  4121. //
  4122. // lplpBuffer - pointer to pointer to buffer where data read
  4123. //
  4124. // dwBufferLength - size of the buffer
  4125. //
  4126. // lpdwBytesAvailable - pointer to returned data available
  4127. //
  4128. //
  4129. //Return Value:
  4130. //
  4131. // DWORD
  4132. // Success - ERROR_SUCCESS
  4133. //
  4134. // Failure - WSA error
  4135. //
  4136. //--*/
  4137. //
  4138. //{
  4139. // DEBUG_ENTER((DBG_SOCKETS,
  4140. // Dword,
  4141. // "ICSocket::DataAvailable2",
  4142. // "%#x, %d, %#x",
  4143. // lpBuffer,
  4144. // dwBufferLength,
  4145. // lpdwBytesAvailable
  4146. // ));
  4147. //
  4148. // //
  4149. // // sanity check parameters
  4150. // //
  4151. //
  4152. // INET_ASSERT(lpdwBytesAvailable != NULL);
  4153. //
  4154. // //
  4155. // // we're about to receive data from the socket. The amount of data currently
  4156. // // on hand must be 0
  4157. // //
  4158. //
  4159. // INET_ASSERT(*lpdwBytesAvailable == 0);
  4160. // INET_ASSERT(lpBuffer != NULL);
  4161. //
  4162. // DWORD error;
  4163. //
  4164. // //
  4165. // // new scheme: actually read the data from sockets into our buffer. This is
  4166. // // the only way on Win95 to determine the correct number of bytes available.
  4167. // // We only perform a single receive
  4168. // //
  4169. //
  4170. // DWORD bufferLeft = dwBufferLength;
  4171. // BOOL eof;
  4172. //
  4173. // error = Receive(&lpBuffer,
  4174. // &dwBufferLength,
  4175. // &bufferLeft, // don't care about this
  4176. // lpdwBytesAvailable,
  4177. // 0,
  4178. // 0,
  4179. // &eof // don't care about this either
  4180. // );
  4181. //
  4182. // DEBUG_LEAVE(error);
  4183. //
  4184. // return error;
  4185. //}
  4186. DWORD
  4187. ICSocket::WaitForReceive(
  4188. IN DWORD Timeout
  4189. )
  4190. /*++
  4191. Routine Description:
  4192. Waits until a receive socket becomes unblocked (readable)
  4193. Arguments:
  4194. Timeout - milliseconds to wait, or INFINITE
  4195. Return Value:
  4196. DWORD
  4197. Success - ERROR_SUCCESS
  4198. Failure - WSA error
  4199. sockets error
  4200. ERROR_WINHTTP_TIMEOUT
  4201. Receive timed out
  4202. --*/
  4203. {
  4204. DEBUG_ENTER((DBG_SOCKETS,
  4205. Dword,
  4206. "ICSocket::WaitForReceive",
  4207. "{%#x} %d",
  4208. m_Socket,
  4209. Timeout
  4210. ));
  4211. struct fd_set read_fds;
  4212. struct fd_set except_fds;
  4213. FD_ZERO(&read_fds);
  4214. FD_ZERO(&except_fds);
  4215. FD_SET(m_Socket, &read_fds);
  4216. FD_SET(m_Socket, &except_fds);
  4217. int n;
  4218. DEBUG_PRINT(SOCKETS,
  4219. INFO,
  4220. ("waiting on socket %#x\n",
  4221. m_Socket
  4222. ));
  4223. TIMEVAL timeout;
  4224. LPTIMEVAL lpTimeout;
  4225. if (Timeout != INFINITE) {
  4226. timeout.tv_sec = Timeout / 1000;
  4227. timeout.tv_usec = (Timeout % 1000) * 1000;
  4228. lpTimeout = &timeout;
  4229. } else {
  4230. lpTimeout = NULL;
  4231. }
  4232. n = _I_select(0, &read_fds, NULL, &except_fds, lpTimeout);
  4233. DWORD error;
  4234. if (n == SOCKET_ERROR) {
  4235. //
  4236. // real error?
  4237. //
  4238. error = _I_WSAGetLastError();
  4239. DEBUG_PRINT(SOCKETS,
  4240. ERROR,
  4241. ("select() returns %d\n",
  4242. error
  4243. ));
  4244. //informational INET_ASSERT(FALSE);
  4245. error = MapInternetError(error);
  4246. } else if (n != 0) {
  4247. if (FD_ISSET(m_Socket, &except_fds)) {
  4248. DEBUG_PRINT(SOCKETS,
  4249. ERROR,
  4250. ("socket %#x exception\n",
  4251. m_Socket
  4252. ));
  4253. error = ERROR_WINHTTP_CONNECTION_ERROR;
  4254. } else {
  4255. //
  4256. // it *must* be unblocked (i.e. readable)
  4257. //
  4258. INET_ASSERT(FD_ISSET(m_Socket, &read_fds));
  4259. DEBUG_PRINT(SOCKETS,
  4260. INFO,
  4261. ("socket %#x unblocked\n",
  4262. m_Socket
  4263. ));
  4264. error = ERROR_SUCCESS;
  4265. }
  4266. } else {
  4267. DEBUG_PRINT(SOCKETS,
  4268. ERROR,
  4269. ("timed out\n"
  4270. ));
  4271. error = ERROR_WINHTTP_TIMEOUT;
  4272. }
  4273. DEBUG_LEAVE(error);
  4274. return error;
  4275. }
  4276. DWORD
  4277. ICSocket::AllocateQueryBuffer(
  4278. OUT LPVOID * lplpBuffer,
  4279. OUT LPDWORD lpdwBufferLength
  4280. )
  4281. /*++
  4282. Routine Description:
  4283. Allocates a query buffer for the socket
  4284. Arguments:
  4285. lplpBuffer - returned pointer to allocated query buffer
  4286. lpdwBufferLength - returned length of allocated query buffer
  4287. Return Value:
  4288. DWORD
  4289. Success - ERROR_SUCCESS
  4290. Failure - ERROR_NOT_ENOUGH_MEMORY
  4291. --*/
  4292. {
  4293. DEBUG_ENTER((DBG_SOCKETS,
  4294. Dword,
  4295. "ICSocket::AllocateQueryBuffer",
  4296. "{%#x/%d} %#x, %#x",
  4297. GetSocket(),
  4298. GetSourcePort(),
  4299. lplpBuffer,
  4300. lpdwBufferLength
  4301. ));
  4302. DWORD error;
  4303. DWORD bufferLength;
  4304. DWORD size = sizeof(bufferLength);
  4305. int serr = _I_getsockopt(m_Socket,
  4306. SOL_SOCKET,
  4307. SO_RCVBUF,
  4308. (char FAR *)&bufferLength,
  4309. (int FAR *)&size
  4310. );
  4311. if (serr != SOCKET_ERROR) {
  4312. bufferLength = min(bufferLength, DEFAULT_SOCKET_QUERY_BUFFER_LENGTH);
  4313. if (bufferLength == 0) {
  4314. bufferLength = DEFAULT_SOCKET_QUERY_BUFFER_LENGTH;
  4315. }
  4316. *lplpBuffer = (LPVOID)ALLOCATE_MEMORY(bufferLength);
  4317. if (*lplpBuffer != NULL) {
  4318. *lpdwBufferLength = bufferLength;
  4319. error = ERROR_SUCCESS;
  4320. } else {
  4321. error = ERROR_NOT_ENOUGH_MEMORY;
  4322. }
  4323. } else {
  4324. error = MapInternetError(_I_WSAGetLastError());
  4325. }
  4326. DEBUG_LEAVE(error);
  4327. return error;
  4328. }
  4329. //
  4330. //VOID
  4331. //ICSocket::FreeQueryBuffer(
  4332. // IN LPVOID lpBuffer
  4333. // )
  4334. //
  4335. ///*++
  4336. //
  4337. //Routine Description:
  4338. //
  4339. // description-of-function.
  4340. //
  4341. //Arguments:
  4342. //
  4343. // lpBuffer -
  4344. //
  4345. //Return Value:
  4346. //
  4347. // None.
  4348. //
  4349. //--*/
  4350. //
  4351. //{
  4352. // lpBuffer = (LPVOID)FREE_MEMORY((HLOCAL)lpBuffer);
  4353. //
  4354. // INET_ASSERT(lpBuffer == NULL);
  4355. //}
  4356. //
  4357. //DWORD
  4358. //ICSocket::GetBytesAvailable(
  4359. // OUT LPDWORD lpdwBytesAvailable
  4360. // )
  4361. //
  4362. ///*++
  4363. //
  4364. //Routine Description:
  4365. //
  4366. // Determines amount of data available to be read from socket
  4367. //
  4368. //Arguments:
  4369. //
  4370. // lpdwBytesAvailable - pointer to returned available length
  4371. //
  4372. //Return Value:
  4373. //
  4374. // DWORD
  4375. // Success - ERROR_SUCCESS
  4376. //
  4377. // Failure -
  4378. //
  4379. //--*/
  4380. //
  4381. //{
  4382. // DEBUG_ENTER((DBG_SOCKETS,
  4383. // Dword,
  4384. // "ICSocket::GetBytesAvailable",
  4385. // "{%#x} %#x",
  4386. // m_Socket,
  4387. // lpdwBytesAvailable
  4388. // ));
  4389. //
  4390. // //INET_ASSERT(m_Socket != INVALID_SOCKET);
  4391. // INET_ASSERT(lpdwBytesAvailable != NULL);
  4392. //
  4393. // //
  4394. // // get the amount from the socket. If the socket has been reset or shutdown
  4395. // // by the server then we expect to get an error, else 0 (== ERROR_SUCCESS)
  4396. // //
  4397. //
  4398. // DWORD error = (DWORD)_I_ioctlsocket(m_Socket,
  4399. // FIONREAD,
  4400. // (u_long FAR *)lpdwBytesAvailable
  4401. // );
  4402. // if (error == SOCKET_ERROR) {
  4403. // error = _I_WSAGetLastError();
  4404. // } else {
  4405. //
  4406. // DEBUG_PRINT(SOCKETS,
  4407. // INFO,
  4408. // ("ioctlsocket(FIONREAD) returns %d\n",
  4409. // *lpdwBytesAvailable
  4410. // ));
  4411. //
  4412. // }
  4413. //
  4414. // DEBUG_LEAVE(error);
  4415. //
  4416. // return error;
  4417. //}
  4418. //
  4419. #if 0
  4420. //not used- remove!
  4421. DWORD
  4422. ICSocket::CreateSocket(
  4423. IN DWORD dwFlags,
  4424. IN int nAddressFamily,
  4425. IN int nType,
  4426. IN int nProtocol
  4427. )
  4428. /*++
  4429. Routine Description:
  4430. Opens a socket handle for this ICSocket object
  4431. Arguments:
  4432. dwFlags - flags to use for new socket
  4433. nAddressFamily - parameter to socket()
  4434. nType - parameter to socket()
  4435. nProtocol - parameter to socket()
  4436. Return Value:
  4437. DWORD
  4438. Success - ERROR_SUCCESS
  4439. Failure - WSA error mapped to INTERNET error
  4440. --*/
  4441. {
  4442. DEBUG_ENTER((DBG_SOCKETS,
  4443. Dword,
  4444. "ICSocket::CreateSocket",
  4445. "%#x, %s (%d), %s (%d), %s (%d)",
  4446. dwFlags,
  4447. MapFamily(nAddressFamily),
  4448. nAddressFamily,
  4449. MapSock(nType),
  4450. nType,
  4451. MapProto(nProtocol),
  4452. nProtocol
  4453. ));
  4454. INET_ASSERT(m_Socket == INVALID_SOCKET);
  4455. int serr;
  4456. DWORD error;
  4457. DWORD dwConnFlags;
  4458. m_Socket = _I_socket(nAddressFamily, nType, nProtocol);
  4459. if (m_Socket == INVALID_SOCKET) {
  4460. DEBUG_PRINT(SOCKETS,
  4461. ERROR,
  4462. ("failed to create socket\n"
  4463. ));
  4464. goto socket_error;
  4465. }
  4466. DEBUG_PRINT(SOCKETS,
  4467. INFO,
  4468. ("created socket %#x\n",
  4469. m_Socket
  4470. ));
  4471. if (dwFlags & SF_NON_BLOCKING) {
  4472. INET_ASSERT(FALSE);
  4473. error = SetNonBlockingMode(TRUE);
  4474. if (error == ERROR_SUCCESS) {
  4475. //
  4476. // ICSocket is non-blocking socket object
  4477. //
  4478. m_dwFlags |= SF_NON_BLOCKING;
  4479. } else {
  4480. goto close_socket;
  4481. }
  4482. }
  4483. //
  4484. // bind our data socket to an endpoint, so that we know an address to
  4485. // tell the FTP server
  4486. //
  4487. struct sockaddr_storage ourDataAddr;
  4488. ourDataAddr.ss_family = (short)nAddressFamily;
  4489. if (nAddressFamily == AF_INET6) {
  4490. struct in_addr6 in6addr_any = IN6ADDR_ANY_INIT;
  4491. ((LPSOCKADDR_IN6)&ourDataAddr)->sin6_port = 0;
  4492. ((LPSOCKADDR_IN6)&ourDataAddr)->sin6_flowinfo = 0;
  4493. ((LPSOCKADDR_IN6)&ourDataAddr)->sin6_addr = in6addr_any;
  4494. ((LPSOCKADDR_IN6)&ourDataAddr)->sin6_scope_id = 0;
  4495. } else {
  4496. ((LPSOCKADDR_IN)&ourDataAddr)->sin_port = 0;
  4497. ((LPSOCKADDR_IN)&ourDataAddr)->sin_addr.s_addr = INADDR_ANY;
  4498. }
  4499. serr = _I_bind(m_Socket,
  4500. (PSOCKADDR)&ourDataAddr,
  4501. sizeof(ourDataAddr)
  4502. );
  4503. if (serr == SOCKET_ERROR) {
  4504. goto socket_error;
  4505. }
  4506. error = ERROR_SUCCESS;
  4507. quit:
  4508. DEBUG_LEAVE(error);
  4509. return error;
  4510. socket_error:
  4511. error = MapInternetError(_I_WSAGetLastError());
  4512. close_socket:
  4513. Close();
  4514. m_dwFlags &= ~SF_NON_BLOCKING;
  4515. goto quit;
  4516. }
  4517. #endif
  4518. DWORD
  4519. ICSocket::GetSockName(
  4520. IN PSOCKADDR psaSockName,
  4521. IN int SockNameSize
  4522. )
  4523. /*++
  4524. Routine Description:
  4525. Returns the socket address for this socket.
  4526. Arguments:
  4527. psaSocketName - pointer to sockaddr buffer to fill in.
  4528. SockNameSize - size of sockaddr buffer;
  4529. Return Value:
  4530. DWORD
  4531. Success - ERROR_SUCCESS
  4532. Failure - WSA error
  4533. --*/
  4534. {
  4535. INET_ASSERT(m_Socket != INVALID_SOCKET);
  4536. INET_ASSERT(psaSockName);
  4537. INET_ASSERT(SockNameSize >= sizeof(SOCKADDR));
  4538. int serr;
  4539. DWORD error;
  4540. serr = ERROR_SUCCESS;
  4541. error = ERROR_SUCCESS;
  4542. //
  4543. // get the address info .
  4544. //
  4545. serr = _I_getsockname(m_Socket,
  4546. psaSockName,
  4547. &SockNameSize
  4548. );
  4549. if ( serr == SOCKET_ERROR )
  4550. {
  4551. error = _I_WSAGetLastError();
  4552. }
  4553. return error;
  4554. }
  4555. DWORD
  4556. ICSocket::Listen(
  4557. VOID
  4558. )
  4559. {
  4560. INET_ASSERT(m_Socket != INVALID_SOCKET);
  4561. DWORD error = ERROR_SUCCESS;
  4562. //
  4563. // Listen on the socket.
  4564. //
  4565. if (_I_listen(m_Socket, 1) == SOCKET_ERROR) {
  4566. error = _I_WSAGetLastError();
  4567. }
  4568. return error;
  4569. }
  4570. DWORD
  4571. ICSocket::DirectConnect(
  4572. PSOCKADDR psaRemoteSock
  4573. )
  4574. /*++
  4575. Routine Description:
  4576. Connects a ICSocket to the remote address
  4577. Arguments:
  4578. psaRemoteSock - pointer to remote socket address (TCP/IP!)
  4579. Return Value:
  4580. DWORD
  4581. Success - ERROR_SUCCESS
  4582. Failure - WSA error mapped to INTERNET error
  4583. --*/
  4584. {
  4585. DEBUG_ENTER((DBG_SOCKETS,
  4586. Dword,
  4587. "ICSocket::DirectConnectSocket",
  4588. "{%#x} %#x",
  4589. m_Socket,
  4590. psaRemoteSock
  4591. ));
  4592. INET_ASSERT(m_Socket != INVALID_SOCKET);
  4593. DWORD error;
  4594. INTERNET_HANDLE_OBJECT * pObject = NULL;
  4595. //
  4596. // we need the thread info for async processing
  4597. //
  4598. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  4599. if (lpThreadInfo == NULL) {
  4600. //informational INET_ASSERT(FALSE);
  4601. error = ERROR_WINHTTP_INTERNAL_ERROR;
  4602. goto quit;
  4603. }
  4604. BOOL isAsync;
  4605. isAsync = lpThreadInfo->IsAsyncWorkerThread;
  4606. //
  4607. // BUGBUG - this is essentially common to ConnectSocket()
  4608. //
  4609. //
  4610. // let another thread know the socket to cancel if it wants to kill
  4611. // this operation
  4612. //
  4613. pObject = (INTERNET_HANDLE_OBJECT * )lpThreadInfo->hObjectMapped;
  4614. if (pObject != NULL) {
  4615. pObject->SetAbortHandle(this);
  4616. }
  4617. #if defined(UNIX) && defined(ux10)
  4618. DEBUG_PRINT(SOCKETS,
  4619. INFO,
  4620. ("connecting to remote address %d.%d.%d.%d, port %d\n",
  4621. ((LPBYTE)&((LPSOCKADDR_IN)psaRemoteSock)->sin_addr)[0],
  4622. ((LPBYTE)&((LPSOCKADDR_IN)psaRemoteSock)->sin_addr)[1],
  4623. ((LPBYTE)&((LPSOCKADDR_IN)psaRemoteSock)->sin_addr)[2],
  4624. ((LPBYTE)&((LPSOCKADDR_IN)psaRemoteSock)->sin_addr)[3],
  4625. _I_ntohs(((LPSOCKADDR_IN)psaRemoteSock)->sin_port)
  4626. ));
  4627. #else
  4628. DEBUG_PRINT(SOCKETS,
  4629. INFO,
  4630. ("connecting to remote address %A, port %d\n",
  4631. psaRemoteSock,
  4632. _I_ntohs(((LPSOCKADDR_IN)psaRemoteSock)->sin_port)
  4633. ));
  4634. #endif
  4635. DWORD connectTime;
  4636. connectTime = GetTickCountWrap();
  4637. int serr;
  4638. PERF_LOG(PE_CONNECT_START,
  4639. m_Socket,
  4640. lpThreadInfo->ThreadId,
  4641. lpThreadInfo->hObject
  4642. );
  4643. if (IsSocks()) {
  4644. // BUGBUG: We only support IPv4 Socks.
  4645. serr = SocksConnect((LPSOCKADDR_IN)psaRemoteSock, sizeof(SOCKADDR_IN));
  4646. } else {
  4647. int RemoteSockSize;
  4648. if (psaRemoteSock->sa_family == AF_INET6) {
  4649. RemoteSockSize = sizeof(SOCKADDR_IN6);
  4650. } else {
  4651. RemoteSockSize = sizeof(SOCKADDR_IN);
  4652. }
  4653. serr = _I_connect(m_Socket, psaRemoteSock, RemoteSockSize);
  4654. }
  4655. if (serr != 0) {
  4656. error = _I_WSAGetLastError();
  4657. //
  4658. // if we are using non-blocking sockets then we need to wait until
  4659. // the connect has completed, or an error occurs
  4660. //
  4661. if (isAsync) {
  4662. if (error == WSAEWOULDBLOCK) {
  4663. DEBUG_PRINT(SOCKETS,
  4664. INFO,
  4665. ("connect() blocked, socket %#x\n",
  4666. m_Socket
  4667. ));
  4668. PERF_LOG(PE_CONNECT_END,
  4669. m_Socket,
  4670. lpThreadInfo->ThreadId,
  4671. lpThreadInfo->hObject
  4672. );
  4673. connectTime = (GetTickCountWrap() - connectTime);
  4674. DEBUG_PRINT(SOCKETS,
  4675. INFO,
  4676. ("connect() resumed, socket %#x, returns %s\n",
  4677. m_Socket,
  4678. InternetMapError(error)
  4679. ));
  4680. } else {
  4681. DEBUG_PRINT(SOCKETS,
  4682. ERROR,
  4683. ("failed to connect non-blocking socket %#x, error %d\n",
  4684. m_Socket,
  4685. error
  4686. ));
  4687. }
  4688. } else {
  4689. DEBUG_PRINT(SOCKETS,
  4690. ERROR,
  4691. ("failed to connect blocking socket %#x, error %d\n",
  4692. m_Socket,
  4693. error
  4694. ));
  4695. }
  4696. } else {
  4697. PERF_LOG(PE_CONNECT_END,
  4698. m_Socket,
  4699. lpThreadInfo->ThreadId,
  4700. lpThreadInfo->hObject
  4701. );
  4702. connectTime = (GetTickCountWrap() - connectTime);
  4703. DEBUG_PRINT(SOCKETS,
  4704. INFO,
  4705. ("socket %#x connected, time = %d mSec\n",
  4706. m_Socket,
  4707. connectTime
  4708. ));
  4709. error = ERROR_SUCCESS;
  4710. }
  4711. if (error != ERROR_SUCCESS) {
  4712. error = MapInternetError(error);
  4713. }
  4714. if (pObject != NULL) {
  4715. pObject->ResetAbortHandle();
  4716. //
  4717. // if the operation has been cancelled, then this error overrides any
  4718. // other
  4719. //
  4720. if (pObject->IsInvalidated()) {
  4721. error = pObject->GetError();
  4722. if (error == ERROR_SUCCESS) {
  4723. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  4724. }
  4725. }
  4726. if (IsAborted()) {
  4727. error = ERROR_WINHTTP_OPERATION_CANCELLED;
  4728. }
  4729. }
  4730. quit:
  4731. INET_ASSERT((pObject != NULL) ? (pObject->GetAbortHandle() == NULL) : TRUE);
  4732. DEBUG_LEAVE(error);
  4733. return error;
  4734. }
  4735. DWORD
  4736. ICSocket::SelectAccept(
  4737. IN ICSocket & acceptSocket,
  4738. IN DWORD dwTimeout
  4739. )
  4740. /*++
  4741. Routine Description:
  4742. Wait until listening socket has connection to accept. We use the socket
  4743. handle in this ICSocket object to accept a connection & create a socket
  4744. handle in another ICSocket object (in acceptSocket)
  4745. Arguments:
  4746. acceptSocket - socket object to wait on
  4747. dwTimeout - number of milliseconds to wait
  4748. Return Value:
  4749. DWORD
  4750. Success - ERROR_SUCCESS
  4751. Failure - WSA error mapped to INTERNET error
  4752. --*/
  4753. {
  4754. DEBUG_ENTER((DBG_SOCKETS,
  4755. Dword,
  4756. "ICSocket::SelectAccept",
  4757. "%#x, %d",
  4758. &acceptSocket,
  4759. dwTimeout
  4760. ));
  4761. DWORD error;
  4762. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  4763. if (lpThreadInfo == NULL) {
  4764. //informational INET_ASSERT(FALSE);
  4765. error = ERROR_WINHTTP_INTERNAL_ERROR;
  4766. goto quit;
  4767. }
  4768. fd_set read_fds;
  4769. fd_set except_fds;
  4770. FD_ZERO(&read_fds);
  4771. FD_ZERO(&except_fds);
  4772. FD_SET(m_Socket, &read_fds);
  4773. FD_SET(m_Socket, &except_fds);
  4774. TIMEVAL timeout;
  4775. timeout.tv_sec = dwTimeout / 1000;
  4776. timeout.tv_usec = dwTimeout % 1000;
  4777. int n;
  4778. n = _I_select(0, &read_fds, NULL, &except_fds, &timeout);
  4779. if (n == 1) {
  4780. if (FD_ISSET(m_Socket, &read_fds)) {
  4781. error = ERROR_SUCCESS;
  4782. } else if (FD_ISSET(m_Socket, &except_fds)) {
  4783. error = ERROR_WINHTTP_CANNOT_CONNECT;
  4784. DEBUG_PRINT(FTP,
  4785. ERROR,
  4786. ("select(): listening socket %#x in error (%d)\n",
  4787. m_Socket,
  4788. error
  4789. ));
  4790. INET_ASSERT(acceptSocket.m_Socket == INVALID_SOCKET);
  4791. } else {
  4792. // Fix PREFIX warning (uninitialized error variable); this case should not happen.
  4793. error = ERROR_WINHTTP_INTERNAL_ERROR;
  4794. }
  4795. } else if (n == 0) {
  4796. //
  4797. // timeout
  4798. //
  4799. error = ERROR_WINHTTP_TIMEOUT;
  4800. DEBUG_PRINT(FTP,
  4801. WARNING,
  4802. ("select() timed out (%d.%d)\n",
  4803. timeout.tv_sec,
  4804. timeout.tv_usec
  4805. ));
  4806. INET_ASSERT(acceptSocket.m_Socket == INVALID_SOCKET);
  4807. } else {
  4808. //
  4809. // socket error
  4810. //
  4811. DEBUG_PRINT(FTP,
  4812. ERROR,
  4813. ("select() returns %d\n",
  4814. _I_WSAGetLastError()
  4815. ));
  4816. INET_ASSERT(acceptSocket.m_Socket == INVALID_SOCKET);
  4817. goto socket_error;
  4818. }
  4819. //
  4820. // if we have a success indication then accept the connection; it may still
  4821. // fail
  4822. //
  4823. if (error == ERROR_SUCCESS) {
  4824. acceptSocket.m_Socket = _I_accept(m_Socket, NULL, NULL);
  4825. if (acceptSocket.m_Socket != INVALID_SOCKET) {
  4826. //
  4827. // copy non-blocking indication to new socket
  4828. //
  4829. INET_ASSERT(!(m_dwFlags & SF_NON_BLOCKING));
  4830. //acceptSocket.m_dwFlags |= (m_dwFlags & SF_NON_BLOCKING);
  4831. } else {
  4832. DEBUG_PRINT(FTP,
  4833. ERROR,
  4834. ("accept() returns %d\n",
  4835. error
  4836. ));
  4837. goto socket_error;
  4838. }
  4839. }
  4840. quit:
  4841. DEBUG_LEAVE(error);
  4842. return error;
  4843. socket_error:
  4844. error = MapInternetError(_I_WSAGetLastError());
  4845. goto quit;
  4846. }
  4847. LPSTR
  4848. MapNetAddressToName(
  4849. IN INTERNET_HANDLE_OBJECT* pSessionObject,
  4850. IN LPSOCKADDR lpSockAddr
  4851. )
  4852. /*++
  4853. Routine Description:
  4854. Given a network address, tries to map it to the corresponding host name. We
  4855. consult the name resolution cache to determine this
  4856. Arguments:
  4857. pSessionObject - pointer session object for access to resolver cache
  4858. lpSockAddr - pointer to SockAddr of address to map
  4859. Return Value:
  4860. LPSTR
  4861. Success - pointer to mapped name, Caller must free
  4862. Failure - NULL
  4863. --*/
  4864. {
  4865. DEBUG_ENTER((DBG_SOCKETS,
  4866. Pointer,
  4867. "MapNetAddressToName",
  4868. "%A",
  4869. lpSockAddr
  4870. ));
  4871. INET_ASSERT(lpSockAddr != NULL);
  4872. LPSTR lpszMappedName = NULL;
  4873. //
  4874. // now try to find the address in the cache. If it's not in the cache then
  4875. // we don't resolve it, simply return the address
  4876. //
  4877. // We were passed the sockaddr for which to look
  4878. DWORD ttl;
  4879. LPADDRINFO CachedAddrInfo;
  4880. LPRESOLVER_CACHE_ENTRY lpResolverCacheEntry;
  4881. if (pSessionObject && pSessionObject->GetResolverCache()->GetResolverCacheList() &&
  4882. ((lpResolverCacheEntry=QueryResolverCache(pSessionObject->GetResolverCache()->GetResolverCacheList(), NULL, lpSockAddr, &CachedAddrInfo, &ttl))!= NULL)) {
  4883. INET_ASSERT(CachedAddrInfo != NULL);
  4884. if (CachedAddrInfo->ai_canonname != NULL)
  4885. lpszMappedName = NewString(CachedAddrInfo->ai_canonname);
  4886. ReleaseResolverCacheEntry(pSessionObject->GetResolverCache()->GetResolverCacheList(), lpResolverCacheEntry);
  4887. }
  4888. DEBUG_PRINT(SOCKETS,
  4889. INFO,
  4890. ("mapped name is %q\n",
  4891. lpszMappedName
  4892. ));
  4893. DEBUG_LEAVE(lpszMappedName);
  4894. return lpszMappedName;
  4895. }