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.

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