Source code of Windows XP (NT5)
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.

431 lines
9.7 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. /////////////////////////////////////////////////////////////////////////////////
  11. //
  12. // ZEvtSyncSocket
  13. // ************ This is an implementation only class ************
  14. // Class ZEvtSyncSocket is a non-supported, implementation only
  15. // class used by the ATL HTTP client class CAtlHttpClient. Do not
  16. // use this class in your code. Use of this class is not supported by Microsoft.
  17. //
  18. /////////////////////////////////////////////////////////////////////////////////
  19. #ifndef __ATLSPRIV_INL__
  20. #define __ATLSPRIV_INL__
  21. #pragma once
  22. inline ZEvtSyncSocket::ZEvtSyncSocket()
  23. {
  24. m_dwCreateFlags = WSA_FLAG_OVERLAPPED;
  25. m_hEventRead = m_hEventWrite = m_hEventConnect = NULL;
  26. m_socket = INVALID_SOCKET;
  27. m_bConnected = false;
  28. m_dwLastError = 0;
  29. m_dwSocketTimeout = ATL_SOCK_TIMEOUT;
  30. g_HttpInit.Init();
  31. }
  32. inline ZEvtSyncSocket::~ZEvtSyncSocket()
  33. {
  34. Close();
  35. }
  36. inline ZEvtSyncSocket::operator SOCKET()
  37. {
  38. return m_socket;
  39. }
  40. inline void ZEvtSyncSocket::Close()
  41. {
  42. if (m_socket != INVALID_SOCKET)
  43. {
  44. m_bConnected = false;
  45. closesocket(m_socket);
  46. m_socket = INVALID_SOCKET;
  47. Term();
  48. }
  49. }
  50. inline void ZEvtSyncSocket::Term()
  51. {
  52. if (m_hEventRead)
  53. {
  54. WSACloseEvent(m_hEventRead);
  55. m_hEventRead = NULL;
  56. }
  57. if (m_hEventWrite)
  58. {
  59. WSACloseEvent(m_hEventWrite);
  60. m_hEventWrite = NULL;
  61. }
  62. if (m_hEventConnect)
  63. {
  64. WSACloseEvent(m_hEventConnect);
  65. m_hEventConnect = NULL;
  66. }
  67. m_socket = INVALID_SOCKET;
  68. }
  69. inline bool ZEvtSyncSocket::Create(WORD wFlags)
  70. {
  71. return Create(PF_INET, SOCK_STREAM, IPPROTO_TCP, wFlags);
  72. }
  73. inline bool ZEvtSyncSocket::Create(short af, short st, short proto, WORD wFlags)
  74. {
  75. bool bRet = true;
  76. if (m_socket != INVALID_SOCKET)
  77. {
  78. m_dwLastError = WSAEALREADY;
  79. return false; // Must close this socket first
  80. }
  81. m_socket = WSASocket(af, st, proto, NULL, 0,
  82. wFlags | m_dwCreateFlags);
  83. if (m_socket == INVALID_SOCKET)
  84. {
  85. m_dwLastError = ::WSAGetLastError();
  86. bRet = false;
  87. }
  88. else
  89. bRet = Init(m_socket, NULL);
  90. return bRet;
  91. }
  92. inline bool ZEvtSyncSocket::Connect(LPCTSTR szAddr, unsigned short nPort)
  93. {
  94. if (m_bConnected)
  95. return true;
  96. bool bRet = true;
  97. CTCPAddrLookup address;
  98. if (SOCKET_ERROR == address.GetRemoteAddr(szAddr, nPort))
  99. {
  100. m_dwLastError = WSAGetLastError();
  101. bRet = false;
  102. }
  103. else
  104. {
  105. bRet = Connect(address.Addr);
  106. }
  107. return bRet;
  108. }
  109. inline bool ZEvtSyncSocket::Connect(const SOCKADDR* psa)
  110. {
  111. if (m_bConnected)
  112. return true; // already connected
  113. DWORD dwLastError;
  114. bool bRet = true;
  115. // if you try to connect the socket without
  116. // creating it first it's reasonable to automatically
  117. // try the create for you.
  118. if (m_socket == INVALID_SOCKET &&
  119. !Create())
  120. return false;
  121. if (WSAConnect(m_socket,
  122. psa, sizeof(SOCKADDR),
  123. NULL, NULL, NULL, NULL))
  124. {
  125. dwLastError = WSAGetLastError();
  126. if (dwLastError != WSAEWOULDBLOCK)
  127. {
  128. m_dwLastError = dwLastError;
  129. bRet = false;
  130. }
  131. else
  132. {
  133. dwLastError = WaitForSingleObject((HANDLE)m_hEventConnect, 10000);
  134. if (dwLastError == WAIT_OBJECT_0)
  135. {
  136. // make sure there were no connection errors.
  137. WSANETWORKEVENTS wse;
  138. ZeroMemory(&wse, sizeof(wse));
  139. WSAEnumNetworkEvents(m_socket, NULL, &wse);
  140. if (wse.iErrorCode[FD_CONNECT_BIT]!=0)
  141. {
  142. m_dwLastError = (DWORD)(wse.iErrorCode[FD_CONNECT_BIT]);
  143. return false;
  144. }
  145. }
  146. }
  147. }
  148. m_bConnected = bRet;
  149. return bRet;
  150. }
  151. inline bool ZEvtSyncSocket::Write(WSABUF *pBuffers, int nCount, DWORD *pdwSize)
  152. {
  153. // if we aren't already connected we'll wait to see if the connect
  154. // event happens
  155. if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)m_hEventConnect , m_dwSocketTimeout))
  156. {
  157. m_dwLastError = WSAENOTCONN;
  158. return false; // not connected
  159. }
  160. // make sure we aren't already writing
  161. if (WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_hEventWrite, 0))
  162. {
  163. m_dwLastError = WSAEINPROGRESS;
  164. return false; // another write on is blocking this socket
  165. }
  166. bool bRet = true;
  167. *pdwSize = 0;
  168. WSAOVERLAPPED o;
  169. m_csWrite.Lock();
  170. o.hEvent = m_hEventWrite;
  171. WSAResetEvent(o.hEvent);
  172. if (WSASend(m_socket, pBuffers, nCount, pdwSize, 0, &o, 0))
  173. {
  174. DWORD dwLastError = WSAGetLastError();
  175. if (dwLastError != WSA_IO_PENDING)
  176. {
  177. m_dwLastError = dwLastError;
  178. bRet = false;
  179. }
  180. }
  181. // wait for write to complete
  182. if (bRet && WAIT_OBJECT_0 == WaitForSingleObject((HANDLE)m_hEventWrite, m_dwSocketTimeout))
  183. {
  184. DWORD dwFlags = 0;
  185. if (WSAGetOverlappedResult(m_socket, &o, pdwSize, FALSE, &dwFlags))
  186. bRet = true;
  187. else
  188. {
  189. m_dwLastError = ::GetLastError();
  190. bRet = false;
  191. }
  192. }
  193. m_csWrite.Unlock();
  194. return bRet;
  195. }
  196. inline bool ZEvtSyncSocket::Write(const unsigned char *pBuffIn, DWORD *pdwSize)
  197. {
  198. WSABUF buff;
  199. buff.buf = (char*)pBuffIn;
  200. buff.len = *pdwSize;
  201. return Write(&buff, 1, pdwSize);
  202. }
  203. inline bool ZEvtSyncSocket::Read(const unsigned char *pBuff, DWORD *pdwSize)
  204. {
  205. // if we aren't already connected we'll wait to see if the connect
  206. // event happens
  207. if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)m_hEventConnect , m_dwSocketTimeout))
  208. {
  209. m_dwLastError = WSAENOTCONN;
  210. return false; // not connected
  211. }
  212. if (WAIT_ABANDONED == WaitForSingleObject((HANDLE)m_hEventRead, 0))
  213. {
  214. m_dwLastError = WSAEINPROGRESS;
  215. return false; // another write on is blocking this socket
  216. }
  217. bool bRet = true;
  218. WSABUF buff;
  219. buff.buf = (char*)pBuff;
  220. buff.len = *pdwSize;
  221. *pdwSize = 0;
  222. DWORD dwFlags = 0;
  223. WSAOVERLAPPED o;
  224. ZeroMemory(&o, sizeof(o));
  225. // protect against re-entrency
  226. m_csRead.Lock();
  227. o.hEvent = m_hEventRead;
  228. WSAResetEvent(o.hEvent);
  229. if (WSARecv(m_socket, &buff, 1, pdwSize, &dwFlags, &o, 0))
  230. {
  231. DWORD dwLastError = WSAGetLastError();
  232. if (dwLastError != WSA_IO_PENDING)
  233. {
  234. m_dwLastError = dwLastError;
  235. bRet = false;
  236. }
  237. }
  238. // wait for the read to complete
  239. if (bRet && WAIT_OBJECT_0 == WaitForSingleObject((HANDLE)o.hEvent, m_dwSocketTimeout))
  240. {
  241. dwFlags = 0;
  242. if (WSAGetOverlappedResult(m_socket, &o, pdwSize, FALSE, &dwFlags))
  243. bRet = true;
  244. else
  245. {
  246. m_dwLastError = ::GetLastError();
  247. bRet = false;
  248. }
  249. }
  250. m_csRead.Unlock();
  251. return bRet;
  252. }
  253. inline bool ZEvtSyncSocket::Init(SOCKET hSocket, void * /*pData=NULL*/)
  254. {
  255. ATLASSERT(hSocket != INVALID_SOCKET);
  256. if (hSocket == INVALID_SOCKET)
  257. {
  258. m_dwLastError = WSAENOTSOCK;
  259. return false;
  260. }
  261. m_socket = hSocket;
  262. // Allocate Events. On error, any open event handles will be closed
  263. // in the destructor
  264. if (NULL != (m_hEventRead = WSACreateEvent()))
  265. if (NULL != (m_hEventWrite = WSACreateEvent()))
  266. if (NULL != (m_hEventConnect = WSACreateEvent()))
  267. {
  268. if (!WSASetEvent(m_hEventWrite) || !WSASetEvent(m_hEventRead))
  269. {
  270. m_dwLastError = ::GetLastError();
  271. return false;
  272. }
  273. if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventRead, FD_READ))
  274. if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventWrite, FD_WRITE))
  275. if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventConnect, FD_CONNECT))
  276. return true;
  277. }
  278. m_dwLastError = ::GetLastError();
  279. return false;
  280. }
  281. inline DWORD ZEvtSyncSocket::GetSocketTimeout()
  282. {
  283. return m_dwSocketTimeout;
  284. }
  285. inline DWORD ZEvtSyncSocket::SetSocketTimeout(DWORD dwNewTimeout)
  286. {
  287. DWORD dwOldTimeout = m_dwSocketTimeout;
  288. m_dwSocketTimeout = dwNewTimeout;
  289. return dwOldTimeout;
  290. }
  291. inline bool ZEvtSyncSocket::SupportsScheme(ATL_URL_SCHEME scheme)
  292. {
  293. // default only supports HTTP
  294. return scheme == ATL_URL_SCHEME_HTTP ? true : false;
  295. }
  296. inline CTCPAddrLookup::CTCPAddrLookup()
  297. {
  298. m_pQuerySet = NULL;
  299. m_pAddr = NULL;
  300. ZeroMemory(&m_saIn, sizeof(m_saIn));
  301. m_saIn.sin_family = PF_INET;
  302. m_saIn.sin_zero[0] = 0;
  303. m_saIn.sin_addr.s_addr = INADDR_NONE;
  304. m_nAddrSize = sizeof(m_saIn);
  305. }
  306. inline CTCPAddrLookup::~CTCPAddrLookup()
  307. {
  308. if (m_pQuerySet)
  309. free ((void*)m_pQuerySet);
  310. }
  311. inline int CTCPAddrLookup::GetRemoteAddr(LPCTSTR szName, short nPort)
  312. {
  313. int nErr = WSAEFAULT;
  314. m_nAddrSize = sizeof(m_saIn);
  315. // first try for the dotted IP address
  316. if (SOCKET_ERROR != WSAStringToAddress( (LPTSTR)szName,
  317. AF_INET,
  318. NULL,
  319. (SOCKADDR*)&m_saIn,
  320. &m_nAddrSize))
  321. {
  322. // Address was a dotted IP address
  323. m_saIn.sin_port = htons(nPort);
  324. m_pAddr = (SOCKADDR*)&m_saIn;
  325. return 0;
  326. }
  327. // else, try to lookup the service
  328. m_nAddrSize = 0;
  329. ATLTRY(m_pQuerySet = (WSAQUERYSET*)malloc(ATL_MAX_QUERYSET));
  330. if (m_pQuerySet)
  331. {
  332. ZeroMemory(m_pQuerySet, sizeof(WSAQUERYSET));
  333. GUID guidsvc = SVCID_TCP(nPort);
  334. AFPROTOCOLS afinet = {PF_INET, IPPROTO_TCP};
  335. m_pQuerySet->dwSize = sizeof(WSAQUERYSET);
  336. m_pQuerySet->dwNameSpace = NS_ALL;
  337. m_pQuerySet->lpafpProtocols = &afinet;
  338. m_pQuerySet->dwNumberOfProtocols = 1;
  339. m_pQuerySet->lpServiceClassId = &guidsvc;
  340. m_pQuerySet->lpszServiceInstanceName = (LPTSTR)szName;
  341. DWORD dwSize = ATL_MAX_QUERYSET;
  342. HANDLE hLookup = NULL;
  343. if (SOCKET_ERROR != WSALookupServiceBegin(m_pQuerySet, LUP_RETURN_ADDR, &hLookup))
  344. {
  345. ATLASSERT(hLookup != NULL);
  346. if (SOCKET_ERROR != WSALookupServiceNext(hLookup, 0, (DWORD*)&dwSize, m_pQuerySet))
  347. {
  348. m_pAddr = m_pQuerySet->lpcsaBuffer[0].RemoteAddr.lpSockaddr;
  349. m_nAddrSize = m_pQuerySet->lpcsaBuffer[0].RemoteAddr.iSockaddrLength;
  350. nErr = 0;
  351. }
  352. else
  353. nErr = (int)GetLastError();
  354. WSALookupServiceEnd(hLookup);
  355. }
  356. }
  357. if (nErr != 0)
  358. {
  359. if (m_pQuerySet)
  360. {
  361. free(m_pQuerySet);
  362. m_pQuerySet = NULL;
  363. }
  364. m_pAddr = NULL;
  365. m_nAddrSize = 0;
  366. }
  367. return nErr;
  368. }
  369. inline const SOCKADDR* CTCPAddrLookup::GetSockAddr()
  370. {
  371. return const_cast<const SOCKADDR*>(m_pAddr);
  372. }
  373. inline int CTCPAddrLookup::GetSockAddrSize()
  374. {
  375. return m_nAddrSize;
  376. }
  377. #endif // __ATLSPRIV_INL__