TDME2  1.9.200
UDPServerClient.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 
3 #include <string>
4 #include <typeinfo>
5 #include <unordered_map>
6 
7 #include <tdme/tdme.h>
11 #include <tdme/utilities/Console.h>
12 #include <tdme/utilities/RTTI.h>
13 #include <tdme/utilities/Time.h>
14 
15 using std::string;
16 using std::unordered_map;
17 
19 
25 
26 UDPServerClient::UDPServerClient(const uint32_t clientId, const string& ip, const uint16_t port) :
27  server(nullptr),
28  ioThread(nullptr),
29  clientId(clientId),
30  ip(ip),
31  port(port),
32  shutdownRequested(false),
33  messageMapSafeMutex("nioudpserverclient_messagemapsafe") {
34  // key
35  key = KEY_PREFIX_UNNAMED + to_string(clientId);
36 }
37 
39  for (const auto& [messageId, message]: messageMapSafe) delete message;
40 }
41 
42 const bool UDPServerClient::setKey(const string &key) {
43  if (key.size() > 0 &&
44  key.size() < 256 &&
45  server->setClientKey(this, key) == true) {
46  this->key = key;
47  return true;
48  } else {
49  return false;
50  }
51 }
52 
54  auto packet = new UDPPacket();
56  return packet;
57 }
58 
59 void UDPServerClient::send(UDPPacket* packet, bool safe, bool deleteFrame) {
60  try {
61  server->sendMessage(this, packet, safe, deleteFrame, UDPServer::MESSAGETYPE_MESSAGE);
62  } catch (NetworkServerException &exception) {
63  // shut down client
64  shutdown();
65 
66  // log
67  Console::println(
68  "UDPServerClient::send(): send failed for client '" +
69  ip +
70  "': " +
71  RTTI::demangle(typeid(exception).name()) +
72  ": " +
73  string(exception.what())
74  );
75  }
76 }
77 
78 bool UDPServerClient::processSafeMessage(const uint32_t messageId) {
79  bool messageProcessed = false;
80 
81  //
83 
84  // check if message has been already processed
85  auto it = messageMapSafe.find(messageId);
86  if (it != messageMapSafe.end()) {
87  // yep, we did
88  messageProcessed = true;
89  auto message = it->second;
90  message->receptions++;
91  } else {
92  // nope, just remember message
93  auto message = new Message();
94  message->messageId = messageId;
95  message->receptions = 1;
96  message->time = Time::getCurrentMillis();
97  // TODO: check for overflow
98  messageMapSafe[messageId] = message;
99  }
100 
101  //
103 
104  // always send acknowlegdement to client
105  auto packet = createPacket();
106  try {
107  server->sendMessage(this, packet, false, true, UDPServer::MESSAGETYPE_ACKNOWLEDGEMENT, messageId);
108  } catch (NetworkServerException &exception) {
109  // shut down client
110  shutdown();
111 
112  // log
113  Console::println(
114  "UDPServerClient::processSafeMessage(): send failed for client '" +
115  ip +
116  "': " +
117  RTTI::demangle(typeid(exception).name()) +
118  ": " +
119  string(exception.what())
120  );
121  }
122 
123  // return if message should be processed
124  return messageProcessed == true?false:true;
125 }
126 
128  auto packet = createPacket();
129  try {
130  packet->putString(key);
131  server->sendMessage(this, packet, true, true, UDPServer::MESSAGETYPE_CONNECT);
132  } catch (NetworkServerException &exception) {
133  // shut down client
134  shutdown();
135 
136  // log
137  Console::println(
138  "UDPServerClient::sendConnected(): send failed for client '" +
139  ip +
140  "': " +
141  RTTI::demangle(typeid(exception).name()) +
142  ": " +
143  string(exception.what())
144  );
145  }
146 }
147 
149  shutdownRequested = true;
150 }
151 
152 void UDPServerClient::onPacketReceived(const UDPPacket* packet, const uint32_t messageId, const uint8_t retries) {
153  // create request
154  auto request = new ServerRequest(
156  this,
158  packet,
159  messageId,
160  retries
161  );
162  // delegate it to thread pool, but make it declinable
163  if (server->workerThreadPool->addElement(request, true) == false) {
164  // element was declined
165  Console::println("UDPServerClient::onPacketReceived(): client request declined from '" + (ip) + "'. Shutting down client");
166  // release client reference
168  // delete packet
169  delete packet;
170  // delete request
171  delete request;
172  // shutdown client
173  shutdown();
174  }
175 }
176 
178  // create request
179  auto request = new ServerRequest(
181  this,
183  nullptr,
186  );
187  // delegate it to thread pool, but make close request not declinable
188  server->workerThreadPool->addElement(request, false);
189  // server call back
190  server->closeClient(this);
191 }
192 
194  // acquire reference for worker
196 
197  // create request
198  auto request = new ServerRequest(
200  this,
202  nullptr,
205  );
206  // delegate it to thread pool, but make close request not declinable
207  server->workerThreadPool->addElement(request, false);
208 }
209 
210 void UDPServerClient::fireEvent(const string &type) {
211  // acquire reference for worker
213 
214  // create request
215  auto request = new ServerRequest(
217  this,
218  type,
219  nullptr,
222  );
223 
224  // delegate it to thread pool, but make close request not declinable
225  server->workerThreadPool->addElement(request, false);
226 }
227 
228 
230  //
232 
233  // check if message has been already processed
234  auto now = Time::getCurrentMillis();
235  auto it = messageMapSafe.begin();
236  while (it != messageMapSafe.end()) {
237  auto message = it->second;
238  if (message->time < now - MESSAGESSAFE_KEEPTIME) {
239  delete it->second;
240  messageMapSafe.erase(it++);
241  continue;
242  }
243  ++it;
244  }
245 
246  //
248 }
249 
250 uint64_t UDPServerClient::getRetryTime(const uint8_t retries) {
251  if (retries == 0) return 0L;
252  if (retries > UDPServerIOThread::MESSAGEACK_RESENDTIMES_TRIES) return 0L;
253  return UDPServerIOThread::MESSAGEACK_RESENDTIMES[retries - 1];
254 }
255 
Base exception class for network server exceptions.
static STATIC_DLL_IMPEXT const char * KEY_PREFIX_UNNAMED
Definition: ServerClient.h:33
static const uint32_t MESSAGE_ID_UNSUPPORTED
Definition: ServerRequest.h:36
static const uint8_t MESSAGE_RETRIES_NONE
Definition: ServerRequest.h:37
bool setClientKey(CLIENT *client, const string &clientKey)
sets a client identification key
Definition: Server.h:163
void closeClient(CLIENT *client)
closes a client connection
Definition: Server.h:189
Base class for network UDP server clients.
void cleanUpSafeMessages()
Clean up safe messages.
void init()
initiates this network client
void send(UDPPacket *packet, bool safe=true, bool deleteFrame=true)
Sends a frame to client, takes over ownership of frame.
void fireEvent(const string &type)
fires an custom event
void close()
Shuts down this network client.
uint64_t getRetryTime(const uint8_t retries)
void shutdown()
Shuts down this network client.
virtual void onPacketReceived(const UDPPacket *packet, const uint32_t messageId=0, const uint8_t retries=0)
Event, which will be called if packet has been received, defaults to worker thread pool.
const bool setKey(const string &key)
sets the clients identification key
static UDPPacket * createPacket()
Creates a packet to be used with send.
virtual ~UDPServerClient()
public destructor, should only be called implicitly by Reference::releaseReference()
void sendConnected()
Sends an connect message to client.
bool processSafeMessage(const uint32_t messageId)
Checks if message has already been processed and sends an acknowlegdement to client / safe client mes...
STATIC_DLL_IMPEXT static const uint64_t MESSAGEACK_RESENDTIMES[MESSAGEACK_RESENDTIMES_TRIES]
unique_ptr< ServerWorkerThreadPool > workerThreadPool
Definition: UDPServer.h:213
static void initializeHeader(UDPPacket *packet)
Writes a empty header to packet.
Definition: UDPServer.cpp:217
void sendMessage(const UDPServerClient *client, UDPPacket *packet, const bool safe, const bool deleteFrame, const MessageType messageType, const uint32_t messageId=MESSAGE_ID_NONE)
pushes a message to be send, takes over ownership of frame
Definition: UDPServer.cpp:455
void unlock()
Unlocks this mutex.
Definition: Mutex.h:54
void lock()
Locks the mutex, additionally mutex locks will block until other locks have been unlocked.
Definition: Mutex.h:47
Console class.
Definition: Console.h:29
Run time type information utility class.
Definition: RTTI.h:14
virtual void releaseReference()
Releases a reference, thus decrementing the counter and delete it if reference counter is zero.
Definition: Reference.h:38
virtual void acquireReference()
Acquires a reference, incrementing the counter.
Definition: Reference.h:31
Time utility class.
Definition: Time.h:20