1 // This is a part of the Active Template Library.
\r
2 // Copyright (C) Microsoft Corporation
\r
3 // All rights reserved.
\r
5 // This source code is only intended as a supplement to the
\r
6 // Active Template Library Reference and related
\r
7 // electronic documentation provided with the library.
\r
8 // See these sources for detailed information regarding the
\r
9 // Active Template Library product.
\r
11 /////////////////////////////////////////////////////////////////////////////////
\r
14 // ************ This is an implementation only class ************
\r
15 // Class ZEvtSyncSocket is a non-supported, implementation only
\r
16 // class used by the ATL HTTP client class CAtlHttpClient. Do not
\r
17 // use this class in your code. Use of this class is not supported by Microsoft.
\r
19 /////////////////////////////////////////////////////////////////////////////////
\r
21 #ifndef __ATLSPRIV_INL__
\r
22 #define __ATLSPRIV_INL__
\r
26 #pragma warning(push)
\r
27 #pragma warning(disable:4312)
\r
29 inline ZEvtSyncSocket::ZEvtSyncSocket()
\r
31 m_dwCreateFlags = WSA_FLAG_OVERLAPPED;
\r
32 m_hEventRead = m_hEventWrite = m_hEventConnect = NULL;
\r
33 m_socket = INVALID_SOCKET;
\r
34 m_bConnected = false;
\r
36 m_dwSocketTimeout = ATL_SOCK_TIMEOUT;
\r
40 inline ZEvtSyncSocket::~ZEvtSyncSocket()
\r
45 inline ZEvtSyncSocket::operator SOCKET()
\r
50 inline void ZEvtSyncSocket::Close()
\r
52 if (m_socket != INVALID_SOCKET)
\r
54 m_bConnected = false;
\r
55 closesocket(m_socket);
\r
56 m_socket = INVALID_SOCKET;
\r
61 inline void ZEvtSyncSocket::Term()
\r
65 WSACloseEvent(m_hEventRead);
\r
66 m_hEventRead = NULL;
\r
70 WSACloseEvent(m_hEventWrite);
\r
71 m_hEventWrite = NULL;
\r
73 if (m_hEventConnect)
\r
75 WSACloseEvent(m_hEventConnect);
\r
76 m_hEventConnect = NULL;
\r
78 m_socket = INVALID_SOCKET;
\r
81 inline bool ZEvtSyncSocket::Create(const ADDRINFOT* pAI, WORD wFlags)
\r
83 return Create(pAI->ai_family, pAI->ai_socktype, pAI->ai_protocol, wFlags);
\r
86 inline bool ZEvtSyncSocket::Create(int af, int st, int proto, WORD wFlags)
\r
89 if (m_socket != INVALID_SOCKET)
\r
91 m_dwLastError = WSAEALREADY;
\r
92 return false; // Must close this socket first
\r
95 m_socket = WSASocket(af, st, proto, NULL, 0,
\r
96 wFlags | m_dwCreateFlags);
\r
97 if (m_socket == INVALID_SOCKET)
\r
99 m_dwLastError = ::WSAGetLastError();
\r
103 bRet = Init(m_socket, NULL);
\r
107 inline bool ZEvtSyncSocket::Connect(LPCTSTR szAddr, unsigned short nPort) throw()
\r
113 CSocketAddr address;
\r
114 // Find address information
\r
115 if ((m_dwLastError = address.FindAddr(szAddr, nPort, 0, PF_UNSPEC, SOCK_STREAM, 0)) != ERROR_SUCCESS)
\r
121 bRet = Connect(address.GetAddrInfo());
\r
126 inline bool ZEvtSyncSocket::Connect(const ADDRINFOT *pAI)
\r
128 if (m_socket == INVALID_SOCKET && !Create(pAI))
\r
131 return Connect((SOCKADDR*)pAI->ai_addr, (int)pAI->ai_addrlen);
\r
134 inline bool ZEvtSyncSocket::Connect(const SOCKADDR* psa, int len)
\r
137 return true; // already connected
\r
142 // if you try to connect the socket without
\r
143 // creating it first it's reasonable to automatically
\r
144 // try the create for you.
\r
145 if (m_socket == INVALID_SOCKET)
\r
148 if (WSAConnect(m_socket,
\r
150 NULL, NULL, NULL, NULL))
\r
152 dwLastError = WSAGetLastError();
\r
153 if (dwLastError != WSAEWOULDBLOCK)
\r
155 m_dwLastError = dwLastError;
\r
160 dwLastError = WaitForSingleObject((HANDLE)m_hEventConnect, m_dwSocketTimeout);
\r
161 if (dwLastError == WAIT_OBJECT_0)
\r
163 // make sure there were no connection errors.
\r
164 WSANETWORKEVENTS wse;
\r
165 ZeroMemory(&wse, sizeof(wse));
\r
166 WSAEnumNetworkEvents(m_socket, NULL, &wse);
\r
167 if (wse.iErrorCode[FD_CONNECT_BIT]!=0)
\r
169 m_dwLastError = (DWORD)(wse.iErrorCode[FD_CONNECT_BIT]);
\r
179 m_bConnected = bRet;
\r
183 inline bool ZEvtSyncSocket::Write(WSABUF *pBuffers, int nCount, DWORD *pdwSize)
\r
185 // if we aren't already connected we'll wait to see if the connect
\r
187 if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)m_hEventConnect , m_dwSocketTimeout))
\r
189 m_dwLastError = WSAENOTCONN;
\r
190 return false; // not connected
\r
193 // make sure we aren't already writing
\r
194 if (WAIT_TIMEOUT == WaitForSingleObject((HANDLE)m_hEventWrite, 0))
\r
196 m_dwLastError = WSAEINPROGRESS;
\r
197 return false; // another write on is blocking this socket
\r
204 o.hEvent = m_hEventWrite;
\r
205 WSAResetEvent(o.hEvent);
\r
206 if (WSASend(m_socket, pBuffers, nCount, pdwSize, 0, &o, 0))
\r
208 DWORD dwLastError = WSAGetLastError();
\r
209 if (dwLastError != WSA_IO_PENDING)
\r
211 m_dwLastError = dwLastError;
\r
216 // wait for write to complete
\r
219 if (WaitForSingleObject((HANDLE)m_hEventWrite, m_dwSocketTimeout) == WAIT_OBJECT_0)
\r
222 if (WSAGetOverlappedResult(m_socket, &o, pdwSize, FALSE, &dwFlags))
\r
226 m_dwLastError = ::GetLastError();
\r
234 m_csWrite.Unlock();
\r
238 inline bool ZEvtSyncSocket::Write(const unsigned char *pBuffIn, DWORD *pdwSize)
\r
241 buff.buf = (char*)pBuffIn;
\r
242 buff.len = *pdwSize;
\r
243 return Write(&buff, 1, pdwSize);
\r
246 inline bool ZEvtSyncSocket::Read(const unsigned char *pBuff, DWORD *pdwSize)
\r
248 // if we aren't already connected we'll wait to see if the connect
\r
250 if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)m_hEventConnect , m_dwSocketTimeout))
\r
252 m_dwLastError = WSAENOTCONN;
\r
253 return false; // not connected
\r
256 if (WAIT_ABANDONED == WaitForSingleObject((HANDLE)m_hEventRead, 0))
\r
258 m_dwLastError = WSAEINPROGRESS;
\r
259 return false; // another write on is blocking this socket
\r
264 buff.buf = (char*)pBuff;
\r
265 buff.len = *pdwSize;
\r
269 ZeroMemory(&o, sizeof(o));
\r
271 // protect against re-entrency
\r
273 o.hEvent = m_hEventRead;
\r
274 WSAResetEvent(o.hEvent);
\r
275 if (WSARecv(m_socket, &buff, 1, pdwSize, &dwFlags, &o, 0))
\r
277 DWORD dwLastError = WSAGetLastError();
\r
278 if (dwLastError != WSA_IO_PENDING)
\r
280 m_dwLastError = dwLastError;
\r
285 // wait for the read to complete
\r
288 if (WAIT_OBJECT_0 == WaitForSingleObject((HANDLE)o.hEvent, m_dwSocketTimeout))
\r
291 if (WSAGetOverlappedResult(m_socket, &o, pdwSize, FALSE, &dwFlags))
\r
295 m_dwLastError = ::GetLastError();
\r
307 inline bool ZEvtSyncSocket::Init(SOCKET hSocket, void * /*pData=NULL*/)
\r
309 ATLASSERT(hSocket != INVALID_SOCKET);
\r
311 if (hSocket == INVALID_SOCKET)
\r
313 m_dwLastError = WSAENOTSOCK;
\r
317 m_socket = hSocket;
\r
319 // Allocate Events. On error, any open event handles will be closed
\r
320 // in the destructor
\r
321 if (NULL != (m_hEventRead = WSACreateEvent()))
\r
322 if (NULL != (m_hEventWrite = WSACreateEvent()))
\r
323 if (NULL != (m_hEventConnect = WSACreateEvent()))
\r
325 if (!WSASetEvent(m_hEventWrite) || !WSASetEvent(m_hEventRead))
\r
327 m_dwLastError = ::GetLastError();
\r
331 if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventRead, FD_READ))
\r
332 if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventWrite, FD_WRITE))
\r
333 if (SOCKET_ERROR != WSAEventSelect(m_socket, m_hEventConnect, FD_CONNECT))
\r
336 m_dwLastError = ::GetLastError();
\r
340 inline DWORD ZEvtSyncSocket::GetSocketTimeout() throw()
\r
342 return m_dwSocketTimeout;
\r
345 inline DWORD ZEvtSyncSocket::SetSocketTimeout(DWORD dwNewTimeout) throw()
\r
347 DWORD dwOldTimeout = m_dwSocketTimeout;
\r
348 m_dwSocketTimeout = dwNewTimeout;
\r
349 return dwOldTimeout;
\r
352 inline bool ZEvtSyncSocket::SupportsScheme(ATL_URL_SCHEME scheme) throw()
\r
354 // default only supports HTTP
\r
355 return scheme == ATL_URL_SCHEME_HTTP ? true : false;
\r
359 #pragma warning(pop)
\r
361 #endif // __ATLSPRIV_INL__
\r