Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cNetSocket.h
Go to the documentation of this file.
1 //
4 //
5 
6 #ifndef _INC_cNetSocket_H
7 #define _INC_cNetSocket_H
8 #ifndef NO_PRAGMA_ONCE
9 #pragma once
10 #endif
11 
12 #include "cNetAddr.h"
13 #include "../WinAPI/WinTypes.h"
19 
20 #ifdef __linux__
21 typedef int SOCKET; // same as HANDLE and cOSHandle
22 #define INVALID_SOCKET (SOCKET)(~0)
23 #define SOCKET_ERROR (-1)
24 #endif // __linux__
25 
26 #ifdef USE_MFC_SOCKET
27 #include <afxsock.h> // MFC socket extensions
28 #endif
29 
30 namespace GrayLib
31 {
33 
34  typedef int IPPROTO_TYPE;
35 
37  {
41 
51  };
52 
54 
55 #ifndef USE_MFC_SOCKET
57  : public CObject
58  , public cNonCopyable
59  {
63 
64  public:
66 
67  protected:
68 #ifdef _WIN32
69  SOCKET m_hSocket;
70 #elif defined(__linux__)
71  cOSHandle m_hSocket;
72 #else
73 #error NOOS
74 #endif
75 
76  protected:
77 
78  SOCKET get_HSocket() const noexcept
79  {
81 #ifdef _WIN32
82  return m_hSocket;
83 #elif defined(__linux__)
84  return m_hSocket.get_Handle();
85 #endif
86  }
87 
88  bool Connect(const struct sockaddr* pAddr, socklen_t nAddrLen)
89  {
91  return(::connect(get_HSocket(), pAddr, nAddrLen) == 0);
92  }
93 
95  {
99  if (::shutdown(get_HSocket(), (int)nHow) == SOCKET_ERROR)
100  return false;
101  return true;
102  }
103 
104  public:
105  cNetSocketBase();
106  virtual ~cNetSocketBase();
107 
108  virtual bool isValidCheck() const noexcept; // override
109  bool isValidSocket() const noexcept
110  {
113 #ifdef _WIN32
114  if (m_hSocket == INVALID_SOCKET || m_hSocket == (SOCKET)HANDLE_NULL) // illegal value for _WIN32.
115  return false;
116 #elif defined(__linux__)
117  if (!m_hSocket.isValidHandle())
118  return false;
119 #endif
120  return true;
121  }
122  operator SOCKET() const noexcept
123  {
124  return get_HSocket();
125  }
126 
127  bool AttachSocket(SOCKET hSocket);
128  SOCKET DetachSocket();
129 
130  virtual void Close();
131 
132  bool Listen(int iMaxBacklogConnections = SOMAXCONN)
133  {
136  ASSERT(isValidSocket());
137  return ::listen(get_HSocket(), iMaxBacklogConnections) == 0;
138  }
139 
140  int Send(const void* pData, int iLen, int nFlags = 0)
141  {
151 
152  ASSERT(isValidSocket());
153 #ifdef __linux__
154  nFlags |= MSG_NOSIGNAL; // Get rid of the SIGPIPE signal for this talking to disconnected sockets. (ESIGNAL)
155 #endif
156  int iRet = ::send(get_HSocket(), (char*)pData, iLen, nFlags);
157  return iRet;
158  }
159  int Receive(void* pBuffer, int nBufLen, int nFlags = 0)
160  {
168  ASSERT(isValidSocket());
169  int iRet = ::recv(get_HSocket(), (char*)pBuffer, nBufLen, nFlags);
170  return iRet;
171  }
172 
173  bool IOCtl(long lCmd, unsigned long* pnArgs) const;
174  bool SetSockOpt(int nOptionName, const void* optval, socklen_t optlen, int nLevel = SOL_SOCKET) const;
175  bool GetSockOpt(int nOptionName, void* optval, socklen_t* pOptLen, int nLevel = SOL_SOCKET) const;
176  };
177 
178 #endif // ! USE_MFC_SOCKET
179 
180  //*******************************************************************************
181 
183  : public cNetSocketBase // Emulate MFC
184  , public cStream // Seek() NOT implemented/supported.
185  {
190 
191  typedef cNetSocketBase SUPER_t;
192  typedef cNetSocket THIS_t;
193 
194  public:
196 #ifdef _WIN32
197  bool m_bBlockingMode;
198 #if ! defined(UNDER_CE)
199  HWND m_hWndAsync;
200 #endif
201 #endif
202 
203  public:
204  cNetSocket();
205  cNetSocket(SOCKET hSocket);
206  cNetSocket(const cNetSocket& src);
207  virtual ~cNetSocket();
208 
209  cNetSocket& operator =(const cNetSocket& src)
210  {
212  AttachSocket(src);
213  return *this;
214  }
215 
216  virtual void Close() override;
217  bool AttachSocket(SOCKET hSocket, long lEvent = 0);
218 
219 #ifdef USE_MFC_SOCKET
220  SOCKET DetachSocket()
221  {
222  return SUPER_t::Detach();
223  }
224 #endif
225 
226  HRESULT BindAddr(const cNetAddress& SockAddr)
227  {
235  ASSERT(isValidSocket());
236 #ifdef USE_MFC_SOCKET
237  if (!SUPER_t::Bind(&SockAddr.ref_Addr(), SockAddr.get_AddrLen()))
238 #else
239  int iRet = ::bind(m_hSocket, &SockAddr.get_Addr(), SockAddr.get_AddrLen());
240  if (iRet != 0)
241 #endif
242  {
243  // Can't bind. port might already be used ? or socket already bound?
244  return GetLastErrorDef();
245  }
246  m_eState = SOCKETSTATE_Bound;
247  return S_OK;
248  }
249 
250  bool Listen(int iMaxBacklogConnections = SOMAXCONN)
251  {
254  ASSERT(isValidSocket());
255  if (!SUPER_t::Listen(iMaxBacklogConnections))
256  {
257  return false;
258  }
259  m_eState = SOCKETSTATE_Listening;
260  return true;
261  }
262 
263  HRESULT ConnectAddr(const cNetAddress& rSockAddr);
264  HRESULT Accept(OUT cNetSocket& rConnectedSocket, OUT cNetAddress* pConnectedSocketAddr=nullptr);
265 
266  //***************************************************************************************
267 
268  HRESULT CreateSocket(sa_family_t nAddressFamily = AF_INET, int nSocketType = SOCK_STREAM, IPPROTO_TYPE nProtocolType = IPPROTO_TCP);
269 
270  HRESULT CreateConnect(const cNetAddress& SockAddr, int nSocketType = SOCK_STREAM, IPPROTO_TYPE nProtocolType = IPPROTO_TCP);
271  HRESULT CreateConnect(const cNetAddressArray& rSockAddrs, int nSocketType = SOCK_STREAM, IPPROTO_TYPE nProtocolType = IPPROTO_TCP);
272 
273  HRESULT CreateBind(const cNetAddress& SockAddr, int nSocketType = SOCK_STREAM, IPPROTO_TYPE nProtocolType = IPPROTO_TCP);
274  HRESULT CreateBindFirst(const cNetAddressArray& rSockAddrs, int nSocketType = SOCK_STREAM, IPPROTO_TYPE nProtocolType = IPPROTO_TCP);
275 
276  HRESULT CloseFlush(TIMESECD_t tWait = 1);
277 
278  static inline HRESULT GetLastError()
279  {
280  return cNetSystem::GetLastError();
281  }
282  static inline HRESULT GetLastErrorDef(HRESULT hResDef = E_FAIL) // static
283  {
285  return cNetSystem::GetLastErrorDef(hResDef);
286  }
287 
288 #ifdef USE_MFC_SOCKET
289  bool isValidSocket() const noexcept
290  {
294  if (m_hSocket == INVALID_SOCKET) // -1 is not valid.
295  return false;
296  if (m_hSocket == (SOCKET)HANDLE_NULL) // 0 is never a valid handle value. ASSUME _WIN32
297  return false;
298  return true;
299  }
300 #endif
301 
302  bool isConnecting() const noexcept
303  {
304  if (m_eState == SOCKETSTATE_Connecting)
305  {
306  DEBUG_CHECK(isValidSocket());
307  return true;
308  }
309  return false;
310  }
311  bool isConnected() const noexcept
312  {
313  if (m_eState == SOCKETSTATE_Established)
314  {
315  DEBUG_CHECK(isValidSocket());
316  return true;
317  }
318  return false;
319  }
320  bool isConnected2() const noexcept
321  {
324  if (m_eState == SOCKETSTATE_Established || m_eState == SOCKETSTATE_Connecting)
325  {
326  DEBUG_CHECK(isValidSocket());
327  return true;
328  }
329  return false;
330  }
331  void SetStateEstablished() noexcept
332  {
335  DEBUG_CHECK(isValidSocket());
336  m_eState = SOCKETSTATE_Established;
337  // ASSERT(isConnected());
338  }
339 
340  SOCKET get_HSocket() const noexcept
341  {
343  return m_hSocket;
344  }
345  HASHCODE_t get_HashCode() const noexcept
346  {
348  DEBUG_CHECK(isValidSocket());
349  return (HASHCODE_t)m_hSocket;
350  }
351 
352  //****************************
353  // A connection is present.
354 
355  bool GetAddrSock(OUT cNetAddress& SockAddr) const;
356  bool GetAddrPeer(OUT cNetAddress& SockAddr) const;
357 
358  HRESULT SendTo(const void* pData, size_t iLen, const cNetAddress& SockAddr, int nFlags = 0);
359  HRESULT ReceiveFrom(void* pBuffer, size_t nBufLen, cNetAddress& SockAddr, int nFlags = 0);
360 
361  cNetAddress get_AddrSock() const; // get the local side of the connection.
362  cNetAddress get_AddrPeer() const; // get the far side of the connection.
363 
364  bool isBlockingMode() const; // FIONBIO set ?
365  bool put_BlockingMode(bool bBlock); // FIONBIO
366  bool put_BlockingTimeoutRx(TIMESECD_t tSec);
367  bool put_BlockingTimeoutTx(TIMESECD_t tSec);
368 
369  bool put_Nagle(bool bDelay); // TCP_NODELAY
370  bool put_KeepAlive(bool bKeepAlive);
371  bool put_Async(bool bAsync); // FIOASYNC
372  bool put_ReuseAddr(bool bReuse);
373 
374  int get_BufferSizeRx() const;
375  bool put_BufferSizeRx(int iSize);
376  int get_BufferSizeTx() const;
377  bool put_BufferSizeTx(int iSize);
378  int get_ReadReady() const; // FIONREAD
379 
380  // cStream support
381  virtual HRESULT WriteX(const void* pData, size_t nDataSize) override;
382  virtual HRESULT ReadX(void* pData, size_t nDataSize) override;
383  virtual HRESULT ReadPeek(void* pData = nullptr, size_t nDataSize = 1) override;
384 
385 #if defined(_WIN32) && ! defined(UNDER_CE)
386  bool AsyncAccept(cNetSocket& socknew, cNetAddress& rAddr, LPCONDITIONPROC pfnCondition, DWORD_PTR dwCallbackData = 0);
387  bool AsyncSelect(HWND hWnd, WINMSG_t uMsg, UINT dwEventMask = FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);
388 #endif
389 
391  };
392 };
393 #endif // _INC_cNetSocket_H
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
UINT WINMSG_t
Supplement _WIN32 "windows.h".
Definition: WinTypes.h:111
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define DEBUG_CHECK(exp)
Definition: cDebugAssert.h:90
short sa_family_t
enum of network family types. e.g. AF_UNSPEC=0, AF_INET = 2, AF_INET6 = 23, AF_NETBIOS = 17,...
Definition: cNetHost.h:19
#define HANDLE_NULL
Invalid OS handle for _WIN32. Not invalid OS handle for linux.
Definition: cOSHandle.h:21
Definition: cNetAddr.h:31
const sockaddr & ref_Addr() const noexcept
Definition: cNetAddr.h:140
socklen_t get_AddrLen() const noexcept
Definition: cNetAddr.h:124
const sockaddr & get_Addr() const noexcept
Definition: cNetAddr.h:135
Definition: cNetSocket.h:59
bool Listen(int iMaxBacklogConnections=SOMAXCONN)
Definition: cNetSocket.h:132
bool ShutDown(SOCKET_ShutDown_TYPE nHow=SOCKET_ShutDown_sends)
Definition: cNetSocket.h:94
int Receive(void *pBuffer, int nBufLen, int nFlags=0)
Definition: cNetSocket.h:159
bool Connect(const struct sockaddr *pAddr, socklen_t nAddrLen)
Definition: cNetSocket.h:88
static ITERATE_t sm_iAllocSockets
Count all open sockets. Watch out for WSADATA.iMaxSockets.
Definition: cNetSocket.h:65
int Send(const void *pData, int iLen, int nFlags=0)
Definition: cNetSocket.h:140
SOCKET get_HSocket() const noexcept
Definition: cNetSocket.h:78
Definition: cNetSocket.h:185
bool isConnecting() const noexcept
Definition: cNetSocket.h:302
static HRESULT GetLastError()
Definition: cNetSocket.h:278
static HRESULT GetLastErrorDef(HRESULT hResDef=E_FAIL)
Definition: cNetSocket.h:282
bool isConnected2() const noexcept
Definition: cNetSocket.h:320
HASHCODE_t get_HashCode() const noexcept
Definition: cNetSocket.h:345
bool isConnected() const noexcept
Definition: cNetSocket.h:311
SOCKETSTATE_TYPE m_eState
What is the state of the socket. e.g. SOCKETSTATE_Disconnected.
Definition: cNetSocket.h:195
SOCKET get_HSocket() const noexcept
Definition: cNetSocket.h:340
void SetStateEstablished() noexcept
Definition: cNetSocket.h:331
HRESULT BindAddr(const cNetAddress &SockAddr)
Definition: cNetSocket.h:226
bool Listen(int iMaxBacklogConnections=SOMAXCONN)
Definition: cNetSocket.h:250
UNITTEST_FRIEND(cNetSocket)
static HRESULT GetLastErrorDef(HRESULT hResDef=E_FAIL)
Definition: cNetSystem.h:105
static HRESULT GetLastError()
Definition: cNetSystem.h:90
Definition: cObject.h:67
Definition: cNonCopyable.h:17
Definition: cOSHandle.h:59
Definition: cStream.h:456
Definition: cMesh.h:22
SOCKETSTATE_TYPE
Definition: cNetSocket.h:37
@ SOCKETSTATE_Connecting
connect() called but not fully connected.
Definition: cNetSocket.h:46
@ SOCKETSTATE_Created
socket() created (isOpen() socket created) but nothing else.
Definition: cNetSocket.h:43
@ SOCKETSTATE_Listening
bound and listening.
Definition: cNetSocket.h:45
@ SOCKETSTATE_Error
similar to above but some other error. dead socket.
Definition: cNetSocket.h:50
@ SOCKETSTATE_Undefined
socket is not created or closed (by calling close()). NULL handle. !isOpen()
Definition: cNetSocket.h:42
@ SOCKETSTATE_Bound
bound to an address:port.
Definition: cNetSocket.h:44
@ SOCKETSTATE_Established
The port is ready to receive/send data from/to the remote peer. maybe accept() was called.
Definition: cNetSocket.h:47
@ SOCKETSTATE_Disconnected
error indicates a remote disconnect. dead socket. not functional socket.
Definition: cNetSocket.h:49
@ SOCKETSTATE_Closing
we are closing this locally. flushing. and going to call close().
Definition: cNetSocket.h:48
UNITTEST2_PREDEF(cQuadtree)
int IPPROTO_TYPE
enum of IPPROTO_TCP,IPPROTO_UDP, etc. getprotobyname() and getprotobynumber()
Definition: cNetSocket.h:34
SOCKET_ShutDown_TYPE
Definition: cNetSocket.h:53
@ SOCKET_ShutDown_receives
Definition: cNetSocket.h:53
@ SOCKET_ShutDown_sends
Definition: cNetSocket.h:53
@ SOCKET_ShutDown_both
Definition: cNetSocket.h:53
int ITERATE_t
like size_t but signed
Definition: Index.h:28
int TIMESECD_t
signed delta seconds. like TIMESEC_t. redefined in TimeUnits.h.
Definition: cTimeSys.h:19
UINT_PTR HASHCODE_t
could hold a pointer converted to a number? maybe 64 or 32 bit ? same as size_t.
Definition: GrayCore.h:116
Definition: cDebugAssert.h:29