guit  0.1
 All Classes Functions Variables Typedefs Enumerations Friends
gnatsocket.hpp
1 //
2 // ccsocket: C++ Classes for TCP/IP and UDP Datagram INET Sockets.
3 // (c) Eric Lecolinet 2016/2020 - https://www.telecom-paris.fr/~elc
4 //
5 // - Socket: TCP/IP or UDP/Datagram IPv4 socket
6 // - ServerSocket: TCP/IP Socket Server
7 // - SocketBuffer: preserves record boundaries when exchanging data
8 // between TCP/IP sockets.
9 //
10 
11 #ifndef gnatsocket_hpp
12 #define gnatsocket_hpp
13 #include <string>
14 
15 #if defined(_WIN32)
16 # include <winsock2.h>
17 # define SOCKSIZE int
18 # define SOCKDATA char
19 #else
20 # include <sys/types.h>
21 # include <sys/socket.h>
22 # define SOCKET int
23 # define SOCKADDR struct sockaddr
24 # define SOCKADDR_IN struct sockaddr_in
25 # define SOCKSIZE ssize_t
26 # define SOCKDATA void
27 # define INVALID_SOCKET -1
28 #endif
29 
30 // ignore SIGPIPES when possible
31 #if defined(MSG_NOSIGNAL)
32 # define NO_SIGPIPE_(flags) (flags | MSG_NOSIGNAL)
33 #else
34 # define NO_SIGPIPE_(flags) (flags)
35 #endif
36 
44 class GNatSocket {
45 public:
50  enum Errors { Failed = -1, InvalidSocket = -2, UnknownHost = -3 };
51 
56  GNatSocket(int type = SOCK_STREAM);
57 
59  GNatSocket(int type, SOCKET sockfd);
60 
62  ~GNatSocket();
63 
67  static void startup();
68  static void cleanup();
70 
75  int connect(const std::string& host, int port);
76 
79  int bind(int port);
80 
84  int bind(const std::string& host, int port);
85 
87  int close();
88 
90  bool isClosed() const { return sockfd_ == INVALID_SOCKET; }
91 
93  SOCKET descriptor() { return sockfd_; }
94 
96  void shutdownInput();
97 
99  void shutdownOutput();
100 
106  SOCKSIZE send(const SOCKDATA* buf, size_t len, int flags = 0) {
107  return ::send(sockfd_, buf, len, NO_SIGPIPE_(flags));
108  }
109 
115  SOCKSIZE receive(SOCKDATA* buf, size_t len, int flags = 0) {
116  return ::recv(sockfd_, buf, len, flags);
117  }
118 
119 #if !defined(_WIN32)
120 
122  SOCKSIZE sendTo(void const* buf, size_t len, int flags,
123  SOCKADDR const* to, socklen_t addrlen) {
124  return ::sendto(sockfd_, buf, len, NO_SIGPIPE_(flags), to, addrlen);
125  }
126 
128  SOCKSIZE receiveFrom(void* buf, size_t len, int flags,
129  SOCKADDR* from, socklen_t* addrlen) {
130  return ::recvfrom(sockfd_, buf, len, flags, from, addrlen);
131  }
132 
134  int setReceiveBufferSize(int size);
135 
137  int setReuseAddress(bool);
138 
140  int setSendBufferSize(int size);
141 
143  int setSoLinger(bool, int linger);
144 
146  int setSoTimeout(int timeout);
147 
149  int setTcpNoDelay(bool);
150 
152  int getReceiveBufferSize() const;
153 
155  bool getReuseAddress() const;
156 
158  int getSendBufferSize() const;
159 
161  bool getSoLinger(int& linger) const;
162 
164  int getSoTimeout() const;
165 
167  bool getTcpNoDelay() const;
168 
169 #endif
170 
171 private:
172  friend class ServerSocket;
173 
174  // Initializes a local INET4 address, returns 0 on success, -1 otherwise.
175  int setLocalAddress(SOCKADDR_IN& addr, int port);
176 
177  // Initializes a remote INET4 address, returns 0 on success, -1 otherwise.
178  int setAddress(SOCKADDR_IN& addr, const std::string& host, int port);
179 
180  SOCKET sockfd_{};
181  GNatSocket(const GNatSocket&) = delete;
182  GNatSocket& operator=(const GNatSocket&) = delete;
183  GNatSocket& operator=(GNatSocket&&) = delete;
184 };
185 
186 
187 
192 public:
195 
196  ~GNatServerSocket();
197 
201  GNatSocket* accept();
202 
205  int bind(int port, int backlog = 50);
206 
208  int close();
209 
211  bool isClosed() const { return sockfd_ == INVALID_SOCKET; }
212 
214  SOCKET descriptor() { return sockfd_; }
215 
216 #if !defined(_WIN32)
217 
219  int setReceiveBufferSize(int size);
220 
222  int setReuseAddress(bool);
223 
225  int setSoTimeout(int timeout);
226 
228  int setTcpNoDelay(bool);
229 
230 #endif
231 
232 private:
233  GNatSocket* createSocket(SOCKET);
234  SOCKET sockfd_{}; // listening socket.
235  GNatServerSocket(const GNatServerSocket&) = delete;
236  GNatServerSocket& operator=(const GNatServerSocket&) = delete;
237  GNatServerSocket& operator=(GNatServerSocket&&) = delete;
238 };
239 
240 
276 public:
282  GNatSocketBuffer(GNatSocket*, size_t inputSize = 8192, size_t ouputSize = 8192);
283  GNatSocketBuffer(GNatSocket&, size_t inputSize = 8192, size_t ouputSize = 8192);
285 
286  ~GNatSocketBuffer();
287 
299  SOCKSIZE readLine(std::string& message);
300 
308  SOCKSIZE writeLine(const std::string& message);
309 
312  SOCKSIZE read(char* buffer, size_t len);
313 
316  SOCKSIZE write(const char* str, size_t len);
317 
319  GNatSocket* socket() { return sock_; }
320 
326  void setReadSeparator(int separ);
327  int readSeparator() const { return insep_; }
328  // @}
329 
335  void setWriteSeparator(int separ);
336  int writeSeparator() const { return outsep_; }
337  // @}
338 
339 private:
340  GNatSocketBuffer(const GNatSocketBuffer&) = delete;
341  GNatSocketBuffer& operator=(const GNatSocketBuffer&) = delete;
342  GNatSocketBuffer& operator=(GNatSocketBuffer&&) = delete;
343 
344 protected:
345  bool retrieveLine(std::string& str, SOCKSIZE received);
346  size_t insize_{}, outsize_{};
347  int insep_{}, outsep_{};
348  GNatSocket* sock_{};
349  struct InputBuffer* in_{};
350 };
351 
352 #endif