Functions.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #include <sstream>
  2. #include <vector>
  3. #include <stdexcept>
  4. #include <bluetooth/bluetooth.h>
  5. #include <bluetooth/hci.h>
  6. #include <bluetooth/l2cap.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #include <sys/poll.h>
  10. #include "Socket.h"
  11. #include "Functions.h"
  12. namespace PresenceDetection {
  13. namespace Bluetooth {
  14. bool Functions::Ping(const std::string& macAddress)
  15. {
  16. struct sockaddr_l2 socketAddress;
  17. int size = 44;
  18. int messageSize = L2CAP_CMD_HDR_SIZE + size;
  19. std::vector<unsigned char> sendBuffer(messageSize);
  20. std::vector<unsigned char> receiveBuffer(messageSize);
  21. Socket socket;
  22. int socketDescriptor = socket.Descriptor();
  23. if (socketDescriptor < 0)
  24. throw std::runtime_error("Can't create Bluetooth socket");
  25. memset(&socketAddress, 0, sizeof(socketAddress));
  26. socketAddress.l2_family = AF_BLUETOOTH;
  27. bdaddr_t bdaddr({{0, 0, 0, 0, 0, 0}});
  28. bacpy(&socketAddress.l2_bdaddr, &bdaddr);
  29. if (bind(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress)) < 0)
  30. throw std::runtime_error("Can't bind socket");
  31. memset(&socketAddress, 0, sizeof(socketAddress));
  32. socketAddress.l2_family = AF_BLUETOOTH;
  33. str2ba(macAddress.c_str(), &socketAddress.l2_bdaddr);
  34. struct timeval timeoutStruct;
  35. timeoutStruct.tv_sec = 3;
  36. timeoutStruct.tv_usec = 0;
  37. fd_set writeDescriptor, errorDescriptor;
  38. FD_ZERO(&writeDescriptor);
  39. FD_ZERO(&errorDescriptor);
  40. FD_SET(socketDescriptor, &writeDescriptor);
  41. FD_SET(socketDescriptor, &errorDescriptor);
  42. int flags;
  43. if((flags = fcntl(socketDescriptor, F_GETFL, 0) < 0))
  44. throw std::runtime_error("Can't get socket options");
  45. if(fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) < 0)
  46. throw std::runtime_error("Can't set socket options");
  47. int ret = 0;
  48. if ((ret = connect(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress)) < 0))
  49. {
  50. if (errno != EINPROGRESS)
  51. return false;
  52. }
  53. if (ret != 0)
  54. {
  55. if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) < 0)
  56. return false;
  57. int error = 0;
  58. socklen_t len = sizeof(error);
  59. if (FD_ISSET(socketDescriptor, &errorDescriptor) || FD_ISSET(socketDescriptor, &writeDescriptor))
  60. {
  61. if (getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
  62. return false;
  63. }
  64. else
  65. {
  66. return false;
  67. }
  68. if (error)
  69. return false;
  70. }
  71. if(fcntl(socketDescriptor, F_SETFL, flags) < 0)
  72. throw std::runtime_error("Can't set socket options");
  73. connect(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress));
  74. memset(&socketAddress, 0, sizeof(socketAddress));
  75. socklen_t optlen = sizeof(socketAddress);
  76. if (getsockname(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), &optlen) < 0)
  77. throw std::runtime_error("Can't get local address");
  78. char str[18];
  79. ba2str(&socketAddress.l2_bdaddr, str);
  80. for (int i = 0; i < size; ++i)
  81. sendBuffer[L2CAP_CMD_HDR_SIZE + i] = (i % 40) + 'A';
  82. int ident = 200;
  83. uint8_t id = ident;
  84. l2cap_cmd_hdr* send_cmd = reinterpret_cast<l2cap_cmd_hdr*>(sendBuffer.data());
  85. l2cap_cmd_hdr* recv_cmd = reinterpret_cast<l2cap_cmd_hdr*>(receiveBuffer.data());
  86. send_cmd->ident = id;
  87. send_cmd->len = htobs(size);
  88. send_cmd->code = L2CAP_ECHO_REQ;
  89. if (send(socketDescriptor, sendBuffer.data(), messageSize, 0) <= 0)
  90. throw std::runtime_error("Send failed");
  91. while (1)
  92. {
  93. struct pollfd pf[1];
  94. pf[0].fd = socketDescriptor;
  95. pf[0].events = POLLIN;
  96. int err;
  97. int timeout = 500;
  98. if ((err = poll(pf, 1, timeout)) < 0)
  99. throw std::runtime_error("Poll failed");
  100. if (!err)
  101. return false;
  102. if ((err = recv(socketDescriptor, receiveBuffer.data(), messageSize, 0)) < 0)
  103. return false;
  104. if (!err)
  105. throw std::runtime_error("Disconnected");
  106. recv_cmd->len = btohs(recv_cmd->len);
  107. if (recv_cmd->ident != id)
  108. continue;
  109. if (recv_cmd->code == L2CAP_ECHO_RSP)
  110. break;
  111. if (recv_cmd->code == L2CAP_COMMAND_REJ)
  112. throw std::runtime_error("Peer doesn't support Echo packets");
  113. }
  114. return true;
  115. }
  116. } // namespace Bluetooth
  117. } // namespace PresenceDetection