libUTL++
NetServer_linux.h
1 #pragma once
2 
4 
5 #if UTL_HOST_OS == UTL_OS_LINUX
6 
8 
9 #include <libutl/Array.h>
10 #include <libutl/FDstream.h>
11 #include <libutl/Hashtable.h>
12 #include <libutl/Queue.h>
13 #include <libutl/Semaphore.h>
14 #include <libutl/ServerSocket.h>
15 #include <libutl/Thread.h>
16 
18 
19 UTL_NS_BEGIN;
20 
22 
23 class NetServerClient;
24 class QueuedConnection;
25 
27 // NetServer ///////////////////////////////////////////////////////////////////////////////////////
29 
37 
39 class NetServer : public Thread
40 {
41  friend class NetServerClient;
43 
44 public:
51  NetServer(size_t maxClients, size_t maxPaused = 1, size_t clientsPerThread = 1)
52  {
53  init(maxClients, maxPaused, clientsPerThread);
54  }
55 
56  virtual void* run(void* arg = nullptr);
57 
62  bool addServer(ServerSocket* serverSocket);
63 
65  void listen();
66 
68  void handlePipeEvent();
69 
71  void handleServerSocketEvent(int fd);
72 
74  void clientDisconnectAll();
75 
80  void clientDisconnect(NetServerClient* client);
81 
82 protected:
88  virtual NetServerClient* clientMake(FDstream* socket, const InetHostAddress& addr);
89 
91  NetServerClient* clientFind(int fd) const;
92 
97  virtual void onClientConnect(NetServerClient* client) = 0;
98 
103  virtual void onClientDisconnect(NetServerClient* client) = 0;
104 
106  virtual bool exiting() const;
107 
108 private:
109  void init(size_t maxClients = size_t_max, size_t maxPaused = 1, size_t clientsPerThread = 1);
110  void deInit();
111  void epiInit();
112 
113  void clientActivate(FDstream* socket, const InetHostAddress& addr, NetServerClient* client);
114 
115  bool clientDeactivate(NetServerClient* client);
116 
121  virtual void clientReadMsg(NetServerClient* client) = 0;
122 
123  ServerSocket* serverFind(int fd);
124 
125  void clientsAdd(NetServerClient* client);
126 
127  NetServerClient* pausedFind();
128 
129 private:
130  using client_ptr_t = std::atomic<NetServerClient*>;
131 
132 private:
133  Array _serverSockets;
134  size_t _pausedMax;
135  size_t _clientsPerThread;
136 
137  // all clients
138  size_t _clientsSize;
139  size_t _clientsMask;
140  size_t _clientsMax;
141  client_ptr_t* _clients;
142  char pad0[UTL_CACHE_LINE_SIZE - sizeof(size_t)];
143  std::atomic_size_t _clientsIndex;
144  char pad1[UTL_CACHE_LINE_SIZE - sizeof(size_t)];
145 
146  int _epi;
147  int _pipe[2];
148  utl::Queue<QueuedConnection> _queuedConnections;
149  utl::Queue<NetServerClient> _queuedThreads;
150  size_t _clientsCount;
151 };
152 
154 // NetServerClient /////////////////////////////////////////////////////////////////////////////////
156 
164 
166 class NetServerClient : public Thread
167 {
168  friend class NetServer;
172 
173 public:
174  NetServerClient(NetServer* server, FDstream* socket, const InetHostAddress& addr);
175 
176  virtual const Object& getKey() const;
177 
178  void listen();
179 
180  virtual void* run(void* arg = nullptr);
181 
182  virtual void pause();
183 
184  virtual void resume(FDstream* socket, const InetHostAddress& addr);
185 
186  inline void
187  wakeup()
188  {
189  _sem.V();
190  }
191 
192  void setSocket(Stream* socket);
193 
194  Stream&
195  socket() const
196  {
197  ASSERTD(_socket != nullptr);
198  return *_socket;
199  }
200 
201  Stream& unbufferedSocket() const;
202 
203  const InetHostAddress&
204  addr() const
205  {
206  return _addr;
207  }
208 
209  void
210  setAddr(const InetHostAddress& addr)
211  {
212  _addr = addr;
213  }
214 
215  bool
216  isVerified() const
217  {
218  return _verified;
219  }
220 
221  void
222  setVerified(bool verified)
223  {
224  _verified = verified;
225  }
226 
227  void
228  exit()
229  {
230  _exit = true;
231  }
232 
233  size_t
234  index() const
235  {
236  return _index;
237  }
238 
239  void
240  setIndex(size_t index)
241  {
242  _index = index;
243  }
244 
245  void
246  setNumClients(size_t numClients)
247  {
248  _numClients = numClients;
249  }
250 
251  bool
252  isPaused() const
253  {
254  return (_numClients > 0) && (_socket == nullptr);
255  }
256 
257  bool
258  isJoinable() const
259  {
260  return (_numClients == 0);
261  }
262 
263 private:
264  void
265  init()
266  {
267  ABORT();
268  }
269  void
270  deInit()
271  {
272  delete _socket;
273  }
274 
275 private:
276  NetServer* _server;
277  Stream* _socket;
278  InetHostAddress _addr;
279  Uint _socketFD;
280  bool _verified;
281  bool _exit;
282  size_t _index;
283  size_t _numClients;
284  utl::Semaphore _sem;
285 };
286 
288 
289 #endif // UTL_HOST_OS == UTL_OS_LINUX
290 
292 
293 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.
SortedCollection that stores objects in an array.
Definition: Array.h:116
Client connection to NetServer.
Local host server socket.
Definition: ServerSocket.h:24
NetServer(size_t maxClients, size_t maxPaused=1, size_t clientsPerThread=1)
Constructor.
Thread of execution.
Definition: Thread.h:31
64-bit unsigned integer.
Definition: Uint.h:27
#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
Stream I/O abstraction.
Definition: Stream.h:68
#define UTL_CLASS_NO_COPY
Declare that a class cannot do copy().
Definition: macros.h:358
Stream with file descriptor.
Definition: FDstream.h:35
Abstract base for multi-threaded network server.
Root of UTL++ class hierarchy.
Definition: Object.h:52
void init()
Initialize UTL++.
#define ASSERTD
Do an assertion in DEBUG mode only.
Internet host address.