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 7.5KB

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