client.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include <client.hpp>
  2. #include <arpa/inet.h>
  3. #include <netdb.h>
  4. #include <string.h>
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <unistd.h>
  8. #include <functional>
  9. #include <cstring>
  10. #include <QDebug>
  11. #include <QByteArray>
  12. #include <iostream>
  13. #include <vector>
  14. #include <future>
  15. #include <headers/kmessage_codec.hpp>
  16. #include <headers/json.hpp>
  17. #include <headers/util.hpp>
  18. using namespace KData;
  19. using json = nlohmann::json;
  20. static const int MAX_BUFFER_SIZE = 2048;
  21. flatbuffers::FlatBufferBuilder builder(1024);
  22. /**
  23. * @brief Client::createMessageHandler
  24. * @param cb
  25. * @return
  26. */
  27. Client::MessageHandler Client::createMessageHandler(
  28. std::function<void()> cb) {
  29. return MessageHandler(cb);
  30. }
  31. /**
  32. * @brief Client::Client
  33. * @constructor
  34. * @param parent
  35. * @param count
  36. * @param arguments
  37. */
  38. Client::Client(QWidget *parent, int count, char** arguments) : QDialog(parent), argc(count), argv(arguments), m_client_socket_fd(-1) {}
  39. /**
  40. * @brief Client::~Client
  41. * @destructor
  42. */
  43. Client::~Client() {
  44. closeConnection();
  45. }
  46. /**
  47. * @brief Client::handleMessages
  48. */
  49. void Client::handleMessages() {
  50. char receive_buffer[2048];
  51. for (;;) {
  52. memset(receive_buffer, 0, 2048);
  53. ssize_t bytes_received = 0;
  54. bytes_received = recv(m_client_socket_fd, receive_buffer, 2048 - 2, 0);
  55. receive_buffer[2047] = 0;
  56. if (bytes_received == 0) {
  57. break;
  58. }
  59. emit Client::messageReceived(QString::fromUtf8(receive_buffer, 2048));
  60. }
  61. memset(receive_buffer, 0, 2048);
  62. ::close(m_client_socket_fd);
  63. }
  64. /**
  65. * @brief Client::start
  66. * @return A meaningless integer
  67. */
  68. void Client::start() {
  69. if (m_client_socket_fd == -1) {
  70. m_client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  71. if (m_client_socket_fd != -1) {
  72. sockaddr_in server_socket;
  73. char* end;
  74. server_socket.sin_family = AF_INET;
  75. auto port_value = strtol(argv[2], &end, 10);
  76. if (port_value < 0 || end == argv[2]) {
  77. return;
  78. }
  79. int socket_option = 1;
  80. // Free up the port to begin listening again
  81. setsockopt(m_client_socket_fd, SOL_SOCKET, SO_REUSEADDR, &socket_option,
  82. sizeof(socket_option));
  83. server_socket.sin_port = htons(port_value);
  84. inet_pton(AF_INET, argv[1], &server_socket.sin_addr.s_addr);
  85. if (::connect(m_client_socket_fd, reinterpret_cast<sockaddr*>(&server_socket),
  86. sizeof(server_socket)) != -1) {
  87. std::string start_operation_string = createOperation("start", {});
  88. // Send operation as an encoded message
  89. sendEncoded(start_operation_string);
  90. // Delegate message handling to its own thread
  91. std::function<void()> message_send_fn = [this]() {
  92. this->handleMessages();
  93. };
  94. MessageHandler message_handler = createMessageHandler(message_send_fn);
  95. // Handle received messages on separate thread
  96. std::thread (message_handler).detach();
  97. } else {
  98. qDebug() << errno;
  99. ::close(m_client_socket_fd);
  100. }
  101. } else {
  102. qDebug() << "Failed to create new connection";
  103. }
  104. } else {
  105. qDebug() << "Connection already in progress";
  106. }
  107. }
  108. /**
  109. * @brief Client::sendMessage
  110. * @param s[in] <const QString&> The message to send
  111. */
  112. void Client::sendMessage(const QString& s) {
  113. if (m_client_socket_fd != -1) {
  114. std::string json_string = createMessage(s.toUtf8().data());
  115. // Send custom message as an encoded message
  116. sendEncoded(json_string);
  117. } else {
  118. qDebug() << "You must first open a connection";
  119. }
  120. }
  121. void Client::sendEncoded(std::string message) {
  122. std::vector<uint8_t> fb_byte_vector{message.begin(), message.end()};
  123. auto byte_vector = builder.CreateVector(fb_byte_vector);
  124. auto k_message = CreateMessage(builder, 69, byte_vector);
  125. builder.Finish(k_message);
  126. uint8_t* encoded_message_buffer = builder.GetBufferPointer();
  127. uint32_t size = builder.GetSize();
  128. qDebug() << "Size is " << size;
  129. uint8_t send_buffer[MAX_BUFFER_SIZE];
  130. memset(send_buffer, 0, MAX_BUFFER_SIZE);
  131. send_buffer[0] = (size & 0xFF) >> 24;
  132. send_buffer[1] = (size & 0xFF) >> 16;
  133. send_buffer[2] = (size & 0xFF) >> 8;
  134. send_buffer[3] = (size & 0xFF);
  135. std::memcpy(send_buffer + 4, encoded_message_buffer, size);
  136. qDebug() << "Ready to send:";
  137. std::string message_to_send{};
  138. for (unsigned int i = 0; i < (size + 4); i++) {
  139. message_to_send += (char)*(send_buffer + i);
  140. }
  141. qDebug() << message_to_send.c_str();
  142. // Send start operation
  143. ::send(m_client_socket_fd, send_buffer, size + 4, 0);
  144. builder.Clear();
  145. }
  146. void Client::closeConnection() {
  147. if (m_client_socket_fd != -1) {
  148. std::string stop_operation_string = createOperation("stop", {});
  149. // Send operation as an encoded message
  150. sendEncoded(stop_operation_string);
  151. // Clean up socket file descriptor
  152. ::shutdown(m_client_socket_fd, SHUT_RDWR);
  153. ::close(m_client_socket_fd);
  154. m_client_socket_fd = -1;
  155. }
  156. }