Functions.cpp 4.0 KB

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