Projektarbeit Line Following Robot bei Prof. Chowanetz im WS22/23
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lfr_socket.cpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "lfr_socket.h"
  2. LFR_Socket::LFR_Socket(ExceptionCallback cb): cb(cb)
  3. {
  4. if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  5. {
  6. throw std::runtime_error("Failed opening the socket");
  7. }
  8. if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) != 0)
  9. {
  10. throw std::runtime_error("Failed setting the socket options");
  11. }
  12. address.sin_family = AF_INET;
  13. address.sin_addr.s_addr = INADDR_ANY;
  14. address.sin_port = htons(8080);
  15. if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) != 0)
  16. {
  17. throw std::runtime_error("Failed binding a name to the socket");
  18. }
  19. if (listen(server_fd, 0) != 0)
  20. {
  21. throw std::runtime_error("Failed listening for connections");
  22. }
  23. }
  24. LFR_Socket::~LFR_Socket()
  25. {
  26. endLoop();
  27. if (thread)
  28. {
  29. thread->join();
  30. }
  31. }
  32. void LFR_Socket::removeListener(LFR_Socket::ListenerKey key)
  33. {
  34. std::lock_guard<std::mutex> lock(mutex);
  35. auto it = std::find_if(std::begin(listeners), std::end(listeners), [&](auto const &val){
  36. return val.first == key;
  37. });
  38. if(it != std::end(listeners))
  39. {
  40. listeners.erase(it);
  41. }
  42. }
  43. void LFR_Socket::addListener(LFR_Socket::ListenerCallback cb, LFR_Socket::ListenerKey key)
  44. {
  45. std::lock_guard<std::mutex> lock(mutex);
  46. listeners.emplace_back(key, std::move(cb));
  47. }
  48. void LFR_Socket::setStop(bool val)
  49. {
  50. std::lock_guard<std::mutex> lock(mutex);
  51. stop = val;
  52. }
  53. void LFR_Socket::createThread()
  54. {
  55. thread = std::make_unique<std::thread>([this](){
  56. bool connected = false;
  57. while(true)
  58. {
  59. LFR_Socket::LFR_Telegram telegram;
  60. bool received = false;
  61. if(!stop && !listeners.empty())
  62. {
  63. try
  64. {
  65. std::lock_guard<std::mutex> lock(mutex);
  66. struct pollfd pollfds[2];
  67. pollfds[0].fd = server_fd;
  68. pollfds[0].events = POLLIN;
  69. pollfds[1].events = POLLIN;
  70. if (poll(pollfds, 2, 200) > 0)
  71. {
  72. if(pollfds[0].revents & POLLIN || pollfds[1].revents & POLLIN)
  73. {
  74. if (!connected && pollfds[0].revents & POLLIN)
  75. {
  76. if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) == -1)
  77. {
  78. throw std::runtime_error("failed accepting connection");
  79. }
  80. else
  81. {
  82. //std::cout << "accepted connection" << std::endl;
  83. pollfds[1].fd = new_socket;
  84. connected = true;
  85. }
  86. }
  87. else if (connected && pollfds[0].revents & POLLIN)
  88. {
  89. //std::cout << "second connection incoming" << std::endl;
  90. int tmp_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen);
  91. close(tmp_socket);
  92. //std::cout << "second connection closed" << std::endl;
  93. }
  94. else if (pollfds[1].revents & POLLIN)
  95. {
  96. bytes_received = recv(new_socket, buffer, sizeof(buffer), 0);
  97. if (bytes_received > 0)
  98. {
  99. received = true;
  100. std::copy(std::begin(buffer), std::end(buffer), std::begin(telegram));
  101. //std::cout << "message received" << std::endl;
  102. }
  103. else if(bytes_received == 0)
  104. {
  105. connected = false;
  106. close(pollfds[1].fd);
  107. //std::cout << "connection closed by peer" << std::endl;
  108. }
  109. }
  110. }
  111. }
  112. }
  113. catch(std::exception const &ex)
  114. {
  115. if(!cb(ex))
  116. {
  117. //callback returned false -> exception not handled -> exit
  118. exit(EXIT_FAILURE);
  119. }
  120. }
  121. //Invoke the callback method (ListenerPair second -> ListenerCallback)
  122. if (received)
  123. {
  124. for(auto &val : listeners)
  125. {
  126. val.second(telegram);
  127. }
  128. }
  129. }
  130. else
  131. {
  132. break;
  133. }
  134. std::this_thread::sleep_for(std::chrono::milliseconds(150));
  135. }
  136. });
  137. }
  138. void LFR_Socket::startLoop()
  139. {
  140. if(thread)
  141. {
  142. //Restart thread if it is running
  143. setStop(true);
  144. thread->join();
  145. setStop(false);
  146. }
  147. createThread();
  148. }
  149. void LFR_Socket::endLoop()
  150. {
  151. setStop(true);
  152. }