RType
ClientSocket.cpp
Go to the documentation of this file.
1 /*
2 ** EPITECH PROJECT, 2023
3 ** R-type
4 ** File description:
5 ** R-type
6 */
7 
8 #include "ClientSocket.hpp"
9 #include <arpa/inet.h>
10 #include <iostream>
11 #include <stdexcept>
12 #include <unistd.h>
13 
14 /*
15  * @brief Construct a new Client Socket:: Client Socket object
16  *
17  */
19 {
20  std::cout << "ClientSocket constructor" << std::endl;
21 
22 #ifdef _WIN32
23  WSADATA wsaData;
24  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
25  std::cout << "WSAStartup failed: " << WSAGetLastError() << std::endl;
26  throw std::runtime_error("Failed to initialize Winsock");
27  }
28  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
29  if (sockfd == INVALID_SOCKET) {
30  std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
31  WSACleanup();
32  throw std::runtime_error("Failed to create socket");
33  }
34 #elif defined(__unix__) || defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
35  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
36  if (sockfd < 0) {
37  std::cout << "Error sockfd < 0 sockfd : " << sockfd << std::endl;
38  throw std::runtime_error("Failed to create socket");
39  }
40 #endif
41 
42  timeout = std::make_unique<struct timeval>();
43  timeout->tv_sec = 0;
44  timeout->tv_usec = 1;
45 
46  loop = true;
47 
48  _isInit = false;
49 
50  std::cout << "Socket created successfully (fd: " << sockfd << ")" << std::endl;
51 }
52 
53 /*
54  * @brief Destroy the Client Socket:: Client Socket object
55  *
56  */
58 {
59 #ifdef _WIN32
60  closesocket(sockfd);
61 #elif defined(__unix__) || defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
62  close(sockfd);
63 #endif
64 }
65 
66 /*
67  * @brief Initialize the client socket
68  *
69  * @param ip
70  * @param port
71  * @return true
72  * @return true if the client is init
73  */
74 bool ClientSocket::init_client(const std::string &ip, int port)
75 {
76  memset(&serv_addr, 0, sizeof(serv_addr));
77  serv_addr.sin_family = AF_INET;
78  serv_addr.sin_port = htons(port);
79  if (inet_pton(AF_INET, ip.c_str(), &serv_addr.sin_addr) <= 0) {
80  return false;
81  }
82 
83  Packet packet{};
84  packet.code = MESSAGE;
85  packet.data_size = 10;
86  packet.data = malloc(packet.data_size);
87  memcpy(packet.data, "connection", packet.data_size);
88 
89  send(&packet, serv_addr);
90  free(packet.data);
91 
92  return true;
93 }
94 
95 /*
96  * @brief Send a packet to the server
97  *
98  * @param packet
99  * @param dest
100  */
101 void ClientSocket::send(Packet *packet, struct sockaddr_in dest)
102 {
103  splitAndSend(packet, dest);
104 }
105 
106 
107 /*
108  * @brief Send a packet to the server
109  *
110  * @param packet
111  * @param dest
112  */
113 void ClientSocket::sendPacket(SplitPacket *packet, struct sockaddr_in dest)
114 {
115  char *buffer = static_cast<char *>(malloc(sizeof(SplitPacket)));
116  memset(buffer, 0, sizeof(SplitPacket));
117  // strcpy(buffer, "test");
118  memcpy(buffer, packet, sizeof(SplitPacket));
119  if (sendto(sockfd, reinterpret_cast<const char *>(buffer), sizeof(SplitPacket), 0, (struct sockaddr *)&dest,
120  sizeof(dest)) < 0) {
121  throw std::runtime_error("Failed to send packet");
122  }
123  free(buffer);
124 }
125 
126 
127 /*
128  * @brief Receive a packet from the server
129  *
130  * @return void
131  */
133 {
134  SplitPacket splitPacket{};
135  struct sockaddr_in cli_addr {
136  };
137  timeval receveidTime{};
138  socklen_t len = sizeof(cli_addr);
139  char *buffer = static_cast<char *>(malloc(sizeof(SplitPacket)));
140  memset(buffer, 0, sizeof(SplitPacket));
141  if (select(sockfd + 1, &_readfds, nullptr, nullptr, timeout.get()) > 0) {
142  if (recvfrom(sockfd, buffer, sizeof(SplitPacket), 0, (struct sockaddr *)&cli_addr, &len) < 0) {
143  throw std::runtime_error("Failed to read from socket");
144  }
145  // std::cout << "Received packet from " << inet_ntoa(cli_addr.sin_addr) << ":" << ntohs(cli_addr.sin_port)
146  // << std::endl;
147  } else {
148  free(buffer);
149  return;
150  }
151  memcpy(&splitPacket, buffer, sizeof(SplitPacket));
152 
153  gettimeofday(&receveidTime, nullptr);
154  _packetBuffer.emplace_back(std::make_unique<SplitPacket>(splitPacket), receveidTime);
155  // std::cout << "Received packet type: " << splitPacket.code << std::endl;
156  free(buffer);
157 }
158 
159 /*
160  * @brief Get a packet from the buffer
161  *
162  * @return std::unique_ptr<Packet>
163  */
165 {
166  std::unique_ptr<Packet> packet = std::make_unique<Packet>();
167  int counter = 0;
168  long long int size = 0;
169  std::unique_ptr<struct timeval> currentTime = std::make_unique<struct timeval>();
170  std::unique_ptr<struct timeval> diffTime = std::make_unique<struct timeval>();
171 
172  auto it2 = _packetBuffer.begin();
173  while (it2 != _packetBuffer.end()) {
174  auto &[splitPacketInBuffer, receveidTimeInBuffer] = *it2;
175  if (splitPacketInBuffer->packet_id == 0 && splitPacketInBuffer->max_packet_id == 0) {
176  packet->code = splitPacketInBuffer->code;
177  packet->data_size = splitPacketInBuffer->max_packet_id * 1024;
178  if (packet->data_size == 0) {
179  packet->data_size = 1024;
180  }
181  packet->data = malloc(packet->data_size);
182  memcpy(packet->data, splitPacketInBuffer->data, packet->data_size);
183  it2 = _packetBuffer.erase(it2);
184  return packet;
185  } else {
186  if (splitPacketInBuffer->packet_id == counter) {
187  size += strlen(splitPacketInBuffer->data);
188  counter++;
189  if (counter == splitPacketInBuffer->max_packet_id) {
190  packet->code = splitPacketInBuffer->code;
191  packet->data_size = size;
192  packet->data = malloc(packet->data_size);
193  memset(packet->data, 0, packet->data_size);
194  int counterAssign = 0;
195  auto it = _packetBuffer.begin();
196  while (it != _packetBuffer.end()) {
197  auto &[splitPacketInBufferAssign, receveidTimeInBufferAssign] = *it;
198  if (splitPacketInBufferAssign->packet_id == counterAssign) {
199  memcpy((char *)packet->data + counterAssign * 1024, splitPacketInBufferAssign->data,
200  strlen(splitPacketInBufferAssign->data));
201  it = _packetBuffer.erase(it);
202  counterAssign++;
203  } else {
204  ++it;
205  }
206  }
207  return packet;
208  }
209  } else {
210  counter = 0;
211  size = 0;
212  }
213  }
214  }
215  free(packet->data);
216 
217  auto it = _packetBuffer.begin();
218  while (it != _packetBuffer.end()) {
219  auto &[splitPacketInBuffer, receveidTimeInBuffer] = *it;
220  gettimeofday(currentTime.get(), nullptr);
221  timersub(currentTime.get(), &receveidTimeInBuffer, diffTime.get());
222  if (diffTime->tv_sec > 0 || diffTime->tv_usec > 100000) {
223  it = _packetBuffer.erase(it);
224  } else {
225  ++it;
226  }
227  }
228  return nullptr;
229 }
230 
231 /*
232  * @brief Receive a packet from the server
233  *
234  * @return std::tuple<std::unique_ptr<Packet>, int>
235  */
237 {
239  std::unique_ptr<Packet> packet = getPacketFromBuffer();
240  if (packet != nullptr) {
241  return std::make_tuple(std::move(packet), 0);
242  }
243  return std::make_tuple(nullptr, 0);
244 }
245 
246 /*std::tuple<std::unique_ptr<Packet>, int> ClientSocket::receive() {
247  bool packet_corrupted = false;
248  packet_test.code = UNDEFINED;
249  struct sockaddr_in cli_addr_code{};
250  socklen_t len_code = sizeof(cli_addr_code);
251  if (select(sockfd + 1, &_readfds, nullptr, nullptr, timeout.get()) > 0) {
252  if (recvfrom(sockfd, reinterpret_cast<char *>(&packet_test.code), sizeof(int), 0, (struct
253 sockaddr*)&cli_addr_code, &len_code) < 0) { throw std::runtime_error("Failed to read from socket");
254  }
255  if (packet_test.code == LOGIN) {
256  std::cout << "packet.code == LOGIN" << std::endl;
257  packet_corrupted = true;
258  }
259  } else {
260  return std::make_tuple(nullptr, 0);
261  }
262 
263 
264  struct sockaddr_in cli_addr_size{};
265  socklen_t len_size = sizeof(cli_addr_size);
266  if (select(sockfd + 1, &_readfds, nullptr, nullptr, timeout.get()) > 0) {
267  if (recvfrom(sockfd, reinterpret_cast<char *>(&packet_test.data_size), sizeof(int), 0, (struct
268 sockaddr*)&cli_addr_size, &len_size) < 0) { throw std::runtime_error("Failed to read from socket");
269  }
270  if (cli_addr_size.sin_addr.s_addr != cli_addr_code.sin_addr.s_addr || cli_addr_size.sin_port !=
271 cli_addr_code.sin_port) { throw std::runtime_error("Failed to read from socket");
272  }
273  } else {
274  return std::make_tuple(nullptr, 0);
275  }
276 
277 
278  packet_test.data = malloc(packet_test.data_size + 1);
279  memset(packet_test.data, 0, packet_test.data_size + 1);
280  struct sockaddr_in cli_addr_data{};
281  socklen_t len_data = sizeof(cli_addr_data);
282  char *buffer = static_cast<char *>(malloc(packet_test.data_size + 1));
283  memset(buffer, 0, packet_test.data_size + 1);
284  if (select(sockfd + 1, &_readfds, nullptr, nullptr, timeout.get()) > 0) {
285  if (recvfrom(sockfd, buffer, packet_test.data_size, 0, (struct sockaddr*)&cli_addr_data, &len_data) < 0) {
286  throw std::runtime_error("Failed to read from socket");
287  }
288  } else {
289  free(buffer);
290  free(packet_test.data);
291  return std::make_tuple(nullptr, 0);
292  }
293  memcpy(packet_test.data, buffer, packet_test.data_size);
294 
295 
296  std::string message = reinterpret_cast<char *>(packet_test.data);
297  if (message == "received") {
298  std::cout << "(Ghost Mode) Received message from " << inet_ntoa(cli_addr_data.sin_addr) << ":" <<
299 ntohs(cli_addr_data.sin_port) << std::endl; return std::make_tuple(nullptr, 0);
300  }
301  lastMessage = message;
302  return std::make_tuple(std::make_unique<Packet>(packet_test), -1);
303 }*/
304 
305 #ifdef _WIN32
306 
307 /*
308  * @brief Read the input from the user
309  *
310  */
311 void ClientSocket::read_input()
312 {
313  while (loop) {
314  std::string message;
315  std::getline(std::cin, message);
316  {
317  std::lock_guard<std::mutex> lock(mtx);
318  input = message;
319  }
320  }
321 }
322 #endif
323 
324 /*
325  * @brief Run the client socket
326  *
327  */
329 {
330  std::cout << "ClientSocket run" << std::endl;
331 
332  std::tuple<std::unique_ptr<Packet>, int> packet_client_id;
333 
334  std::unique_ptr<Packet> packet;
335 
336 #ifdef _WIN32
337  inputThread = std::thread(&ClientSocket::read_input, this);
338 
339  while (loop) {
340  init_fd_set();
341  std::string message;
342  {
343  std::lock_guard<std::mutex> lock(mtx);
344  if (!input.empty()) {
345  message = input;
346  input.clear();
347  }
348  }
349  if (!message.empty()) {
350  std::unique_ptr<Packet> packet = std::make_unique<Packet>();
351  packet->code = MESSAGE;
352  packet->data_size = message.size();
353  packet->data = malloc(packet->data_size);
354  memcpy(packet->data, message.c_str(), packet->data_size);
355  send(packet.get(), serv_addr);
356  }
357  if (FD_ISSET(sockfd, &_readfds)) {
358  if (select(sockfd + 1, &_readfds, nullptr, nullptr, timeout.get()) > 0) {
359  receive();
360  }
361  }
362  }
363 
364  inputThread.join();
365 #elif defined(__unix__) || defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
366  while (loop) {
368  listen_server();
369  if (lastMessage == "exit") {
370  break;
371  }
372  }
373 #endif
374 }
375 
376 /*
377  * @brief Listen the server
378  *
379  * @return std::tuple<std::unique_ptr<Packet>, int>
380  */
382 {
383  std::cout << "listen_server" << std::endl;
384  int action = select(FD_SETSIZE, &_readfds, nullptr, nullptr, nullptr);
385  std::cout << "action: " << action << std::endl;
386  if (action == -1) {
387  throw std::runtime_error("Error: select failed");
388  } else if (action == 0) {
389  throw std::runtime_error("Error: select timeout");
390  } else {
391  std::cout << "FD_ISSET(STDIN_FILENO, &_readfds): " << FD_ISSET(0, &_readfds) << std::endl;
392  if (FD_ISSET(0, &_readfds)) {
393  std::string message;
394  if (!std::getline(std::cin, message)) {
395  loop = false;
396  return std::make_tuple(nullptr, 0);
397  }
398  std::unique_ptr<Packet> packet = std::make_unique<Packet>();
399  packet->code = MESSAGE;
400  packet->data_size = message.size();
401  packet->data = malloc(packet->data_size);
402  memcpy(packet->data, message.c_str(), packet->data_size);
403  send(packet.get(), serv_addr);
404  }
405  if (FD_ISSET(sockfd, &_readfds)) {
406  return receive();
407  }
408  }
409  return std::make_tuple(nullptr, 0);
410 }
411 
412 /*
413  * @brief Initialize the fd_set
414  *
415  */
417 {
418  FD_ZERO(&_readfds);
419 #ifndef _WIN32
420  FD_SET(0, &_readfds);
421 #endif
422  FD_SET(sockfd, &_readfds);
423 }
424 
425 /*
426  * @brief Get the Last Message object
427  *
428  * @return boolean siInit
429  */
430 bool ClientSocket::isInit() const
431 {
432  return _isInit;
433 }
434 
435 /*
436  * @brief Set the Last Message object
437  *
438  * @param init
439  */
440 void ClientSocket::setInit(bool init)
441 {
442  _isInit = init;
443 }
444 
445 /*
446  * @brief Split a packet and send it
447  *
448  * @param packet
449  * @param dest
450  */
451 void ClientSocket::splitAndSend(Packet *packet, struct sockaddr_in dest)
452 {
453  std::unique_ptr<SplitPacket> splitPacket = std::make_unique<SplitPacket>();
454  splitPacket->code = packet->code;
455  int i;
456 
457  if (packet->data_size < 1024) {
458  splitPacket->packet_id = 0;
459  splitPacket->max_packet_id = 0;
460  splitPacket->data[0] = '\0';
461  memset(splitPacket->data, 0, 1024);
462  memcpy(splitPacket->data, packet->data, packet->data_size);
463  sendPacket(splitPacket.get(), dest);
464  } else {
465  splitPacket->max_packet_id = packet->data_size / 1024 + 1;
466  for (i = 0; i < packet->data_size / 1024; i++) {
467  splitPacket->packet_id = i;
468  memset(splitPacket->data, 0, 1024);
469  memcpy(splitPacket->data, (char *)packet->data + i * 1024, 1024);
470  sendPacket(splitPacket.get(), dest);
471  }
472  int rest = packet->data_size % 1024;
473  if (rest > 0) {
474  splitPacket->packet_id = i;
475  memset(splitPacket->data, 0, 1024);
476  memcpy(splitPacket->data, (char *)packet->data + i * 1024 + 1, rest);
477  sendPacket(splitPacket.get(), dest);
478  }
479  free(packet->data);
480  }
481 }