Gamedev Framework (gf)  0.17.0
A C++14 framework for 2D games
Socket.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2019 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_SOCKET_H
22 #define GF_SOCKET_H
23 
24 #include <cstddef>
25 #include <cstdint>
26 #include <string>
27 
28 #ifdef _WIN32
29 #include <winsock2.h>
30 #else
31 #include <unistd.h>
32 #endif
33 
34 #include "ArrayRef.h"
35 #include "BufferRef.h"
36 #include "Portability.h"
37 #include "SocketAddress.h"
38 #include "SocketGuard.h"
39 
40 namespace gf {
41 #ifndef DOXYGEN_SHOULD_SKIP_THIS
42 inline namespace v1 {
43 #endif
44 
45 #ifndef DOXYGEN_SHOULD_SKIP_THIS
46 #ifdef _WIN32
47  using SocketHandle = SOCKET;
48  constexpr SocketHandle InvalidSocketHandle = INVALID_SOCKET;
49 #else
50  using SocketHandle = int;
51  constexpr SocketHandle InvalidSocketHandle = -1;
52 #endif
53 #else
54 
63  using SocketHandle = implementation-defined;
64 
75  constexpr SocketHandle InvalidSocketHandle = implemetation-defined;
76 #endif
77 
84  enum class SocketStatus {
85  Data,
86  Block,
87  Close,
88  Error,
89  };
90 
99  std::size_t length;
100  };
101 
109  class GF_API Socket : private SocketGuard {
110  public:
116  ~Socket();
117 
121  Socket(const Socket&) = delete;
122 
126  Socket& operator=(const Socket&) = delete;
127 
133  Socket(Socket&& other) noexcept;
134 
141  Socket& operator=(Socket&& other) noexcept;
142 
148  operator bool () const noexcept {
149  return m_handle != InvalidSocketHandle;
150  }
151 
157  SocketAddress getLocalAddress() const;
158 
164  void setBlocking();
165 
171  void setNonBlocking();
172 
173  protected:
174 #ifndef DOXYGEN_SHOULD_SKIP_THIS
175  Socket()
176  : m_handle(InvalidSocketHandle)
177  {
178 
179  }
180 
181  void setHandle(SocketHandle handle) {
182  m_handle = handle;
183  }
184 
185  SocketHandle getHandle() const {
186  return m_handle;
187  }
188 
189  static bool nativeCloseSocket(SocketHandle handle);
190  static bool nativeSetBlockMode(SocketHandle handle, bool blocking);
191  static bool nativeWouldBlock(int err);
192 
193 #ifdef _WIN32
194  using SendLengthType = int;
195  using SendPointerType = const char *;
196  using RecvLengthType = int;
197  using RecvPointerType = char *;
198 #else
199  using SendLengthType = std::size_t;
200  using SendPointerType = const void *;
201  using RecvLengthType = std::size_t;
202  using RecvPointerType = void *;
203 #endif
204 
205  static SendLengthType sendLength(ArrayRef<uint8_t> buffer);
206  static SendPointerType sendPointer(ArrayRef<uint8_t> buffer);
207 
208  static RecvLengthType recvLength(BufferRef<uint8_t> buffer);
209  static RecvPointerType recvPointer(BufferRef<uint8_t> buffer);
210 
211  static int getErrorCode();
212  static std::string getErrorString();
213 
214 #ifdef _WIN32
215  static constexpr int InvalidCommunication = SOCKET_ERROR;
216 #else
217  static constexpr ssize_t InvalidCommunication = -1;
218 #endif
219 
220  protected:
221  enum SocketType : int {
222  Tcp = SOCK_STREAM,
223  Udp = SOCK_DGRAM,
224  };
225 
226  struct SocketAddressInfo {
227  SocketFamily family;
228  SocketType type;
229  SocketAddress address;
230  };
231 
232  static constexpr int NoFlag = 0;
233 
234  static std::vector<SocketAddressInfo> getRemoteAddressInfo(const std::string& hostname, const std::string& service, SocketType type, SocketFamily family = SocketFamily::Unspec);
235  static std::vector<SocketAddressInfo> getLocalAddressInfo(const std::string& service, SocketType type, SocketFamily family = SocketFamily::Unspec);
236 #endif
237 
238  private:
239  static std::vector<SocketAddressInfo> getAddressInfoEx(const char *hostname, const char *service, int flags, SocketType type, SocketFamily family);
240 
241  protected:
242 #ifndef DOXYGEN_SHOULD_SKIP_THIS
243  struct Header {
244  uint8_t data[8];
245  };
246 
247  static constexpr Header encodeHeader(uint64_t size) {
248  Header header = {{ 0, 0, 0, 0, 0, 0, 0, 0 }};
249 
250  for (int i = 0; i < 8; ++i) {
251  header.data[8 - i - 1] = static_cast<uint8_t>(size % 0x100);
252  size >>= 8;
253  }
254 
255  return header;
256  }
257 
258  static constexpr uint64_t decodeHeader(const Header& header) {
259  uint64_t size = 0;
260 
261  for (uint64_t x : header.data) {
262  size = (size << 8) + x;
263  }
264 
265  return size;
266  }
267 #endif
268  private:
269  friend class SocketSelector;
270  SocketHandle m_handle;
271  };
272 
273 #ifndef DOXYGEN_SHOULD_SKIP_THIS
274 }
275 #endif
276 }
277 
278 #endif // GF_SOCKET_H
Some data has been sent or received.
SocketFamily
A socket family.
Definition: SocketAddress.h:50
The result of a socket operation.
Definition: Socket.h:97
Unspecified (either IPv4 or IPv6)
The connection is closed.
constexpr BufferRef< T > buffer(T *data, std::size_t size)
Create a reference to a buffer.
Definition: BufferRef.h:211
An error occurred.
Definition: SocketSelector.h:49
The namespace for gf classes.
Definition: Action.h:35
SocketStatus status
The status of the operation.
Definition: Socket.h:98
constexpr SocketHandle InvalidSocketHandle
An invalid socket handle.
Definition: Socket.h:75
A socket selector.
Definition: SocketSelector.h:59
A guard to handle library initialization.
Definition: SocketGuard.h:42
std::size_t length
The length of sent or received data.
Definition: Socket.h:99
SocketStatus
The status of a socket operation.
Definition: Socket.h:84
The socket would have blocked.
implementation-defined SocketHandle
A native socket handle.
Definition: Socket.h:63
A network socket.
Definition: Socket.h:109
A socket address.
Definition: SocketAddress.h:78