libUTL++
NetServer_mingw.h
1 #pragma once
2 
4 
5 #if UTL_HOST_OS == UTL_OS_MINGW
6 
8 
9 #include <libutl/win32api.h>
10 #include <libutl/Array.h>
11 #include <libutl/FDstream.h>
12 #include <libutl/Hashtable.h>
13 #include <libutl/List.h>
14 #include <libutl/Mutex.h>
15 #include <libutl/RingBuffer.h>
16 #include <libutl/Semaphore.h>
17 #include <libutl/TCPserverSocket.h>
18 #include <libutl/Thread.h>
19 
21 
22 UTL_NS_BEGIN;
23 
25 
26 class NetServerClient;
27 
29 // NetServer ///////////////////////////////////////////////////////////////////////////////////////
31 
39 
41 class NetServer : public Thread
42 {
43  friend class NetServerClient;
44  UTL_CLASS_DECL_ABC(NetServer, Thread);
45 
46 public:
53  NetServer(size_t maxClients, size_t maxPaused = 1, size_t clientsPerThread = 1)
54  {
55  init(maxClients, maxPaused, clientsPerThread);
56  }
57 
58  virtual void* run(void* arg = nullptr);
59 
64  bool addServer(TCPserverSocket* serverSocket);
65 
69  void listen();
70 
72  void clientDisconnectAll();
73 
78  void clientDisconnect(NetServerClient* client);
79 
80 protected:
86  virtual NetServerClient* clientMake(FDstream* socket, const InetHostAddress& addr);
87 
89  NetServerClient* clientFind(int fd) const;
90 
96  virtual void clientWriteServerBusyMsg(Stream& os) = 0;
97 
102  virtual void onClientConnect(NetServerClient* client) = 0;
103 
108  virtual void onClientDisconnect(NetServerClient* client) = 0;
109 
111  virtual bool exiting() const;
112 
113 private:
114  void init(size_t maxClients = size_t_max, size_t maxPaused = 1, size_t clientsPerThread = 1);
115  void deInit();
116 
117  bool clientDeactivate(NetServerClient* client);
118 
123  virtual void clientReadMsg(NetServerClient* client) = 0;
124 
125  TCPserverSocket* serverFind(int fd);
126 
127  void cleanupJoinable();
128 
129  void cleanupPaused();
130 
131  void clientsAdd(NetServerClient* client);
132 
133  bool pausedAdd(NetServerClient* client);
134 
135  NetServerClient* pausedFind();
136 
137 private:
138  using client_ptr_t = std::atomic<NetServerClient*>;
139 
140 private:
141  Array _serverSockets;
142  fd_set _serverFDs;
143  int _maxFD;
144  size_t _clientsPerThread;
145 
146  // all clients
147  size_t _clientsSize;
148  size_t _clientsMask;
149  size_t _clientsMax;
150  client_ptr_t* _clients;
151 
152  // shared counters
153  char pad0[UTL_CACHE_LINE_SIZE - sizeof(size_t)];
154  std::atomic_size_t _clientsCount;
155  char pad1[UTL_CACHE_LINE_SIZE - sizeof(size_t)];
156  std::atomic_size_t _clientsIndex;
157 
158  // paused clients
160 
161  // joinable clients
163 };
164 
166 // NetServerClient /////////////////////////////////////////////////////////////////////////////////
168 
176 
178 class NetServerClient : public Thread
179 {
180  friend class NetServer;
181  UTL_CLASS_DECL(NetServerClient, Thread);
184 
185 public:
186  NetServerClient(NetServer* server, FDstream* socket, const InetHostAddress& addr);
187 
188  virtual const Object& getKey() const;
189 
190  void listen();
191 
192  virtual void* run(void* arg = nullptr);
193 
194  virtual void pause();
195 
196  virtual void resume(FDstream* socket, const InetHostAddress& addr);
197 
198  inline void
199  wakeup()
200  {
201  _sem.V();
202  }
203 
204  void setSocket(Stream* stream);
205 
206  Stream&
207  socket() const
208  {
209  ASSERTD(_socket != nullptr);
210  return *_socket;
211  }
212 
213  Stream& unbufferedSocket() const;
214 
215  const InetHostAddress&
216  addr() const
217  {
218  return _addr;
219  }
220 
221  void
222  setAddr(const InetHostAddress& addr)
223  {
224  _addr = addr;
225  }
226 
227  bool
228  isVerified() const
229  {
230  return _verified;
231  }
232 
233  void
234  setVerified(bool verified)
235  {
236  _verified = verified;
237  }
238 
239  void
240  exit()
241  {
242  _exit = true;
243  }
244 
245  size_t
246  index() const
247  {
248  return _index;
249  }
250 
251  void
252  setIndex(size_t index)
253  {
254  _index = index;
255  }
256 
257  void
258  setNumClients(size_t numClients)
259  {
260  _numClients = numClients;
261  }
262 
263  bool
264  isPaused() const
265  {
266  return (_numClients > 0) && (_socket == nullptr);
267  }
268 
269  bool
270  isJoinable() const
271  {
272  return (_numClients == 0);
273  }
274 
275 private:
276  void
277  init()
278  {
279  ABORT();
280  }
281  void
282  deInit()
283  {
284  delete _socket;
285  }
286 
287 private:
288  NetServer* _server;
289  Stream* _socket;
290  InetHostAddress _addr;
291  Uint _socketFD;
292  bool _verified;
293  bool _exit;
294  size_t _index;
295  size_t _numClients;
296  utl::Semaphore _sem;
297 };
298 
300 
301 #endif // UTL_HOST_OS == UTL_OS_MINGW
302 
304 
305 UTL_NS_END;
void deInit()
De-initialize UTL++.
Counter for resources shared between threads.
Definition: Semaphore.h:23
#define UTL_CLASS_DECL(DC, BC)
Declaration of standard UTL++ functionality for a non-template class.
Definition: macros.h:688
const size_t size_t_max
Maximum size_t value.
Thread-safe fixed-size queue.
Definition: RingBuffer.h:19
#define UTL_CLASS_DECL_ABC(DC, BC)
Declaration of standard UTL++ functionality for an abstract base class (ABC).
Definition: macros.h:650
#define ABORT()
Immediately terminates the program.
Definition: macros.h:59
#define UTL_CLASS_NO_SERIALIZE
Declare that a class cannot do serialize().
Definition: macros.h:384
#define UTL_CLASS_NO_COPY
Declare that a class cannot do copy().
Definition: macros.h:358
void init()
Initialize UTL++.
#define ASSERTD
Do an assertion in DEBUG mode only.