From 6c3a7808db2ba7d3699aaa4c813da4eea810e577 Mon Sep 17 00:00:00 2001 From: Paul Nettle Date: Mon, 2 Oct 2017 11:02:09 -0500 Subject: Improved threading support, cleaner initialization process and added the ability to wait for threaded responses from HCI commands. --- src/HciSocket.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src/HciSocket.cpp') diff --git a/src/HciSocket.cpp b/src/HciSocket.cpp index 214ef85..c3cadc3 100644 --- a/src/HciSocket.cpp +++ b/src/HciSocket.cpp @@ -92,7 +92,7 @@ bool HciSocket::connect() return false; } - Logger::debug(SSTR << "Connected to HCI control socket (file descriptor = " << fdSocket << ")"); + Logger::debug(SSTR << "Connected to HCI control socket (fd = " << fdSocket << ")"); return true; } @@ -108,8 +108,15 @@ void HciSocket::disconnect() { if (isConnected()) { - close(fdSocket); + Logger::debug("HciSocket disconnecting"); + + if (close(fdSocket) != 0) + { + logErrno("close(fdSocket)"); + } + fdSocket = -1; + Logger::trace("HciSocket closed"); } } @@ -124,8 +131,11 @@ bool HciSocket::read(std::vector &response) const // Fill our response with empty data response.resize(kResponseMaxSize, 0); - // Ensure we have blocking I/O - fcntl(fdSocket, F_SETFL, 0); + // Wait for data or a cancellation + if (!waitForDataOrShutdown()) + { + return false; + } // Block until we receive data, a disconnect, or a signal ssize_t bytesRead = ::recv(fdSocket, &response[0], kResponseMaxSize, MSG_WAITALL); @@ -146,7 +156,7 @@ bool HciSocket::read(std::vector &response) const } else if (bytesRead == 0) { - Logger::error(" + Peer closed the socket"); + Logger::error("Peer closed the socket"); response.resize(0); return false; } @@ -155,7 +165,7 @@ bool HciSocket::read(std::vector &response) const response.resize(bytesRead); std::string dump = ""; - dump += "> Read " + std::to_string(response.size()) + " bytes\n"; + dump += " > Read " + std::to_string(response.size()) + " bytes\n"; dump += Utils::hex(response.data(), response.size()); Logger::debug(dump); @@ -176,7 +186,7 @@ bool HciSocket::write(std::vector buffer) const bool HciSocket::write(const uint8_t *pBuffer, size_t count) const { std::string dump = ""; - dump += "> Writing " + std::to_string(count) + " bytes\n"; + dump += " > Writing " + std::to_string(count) + " bytes\n"; dump += Utils::hex(pBuffer, count); Logger::debug(dump); @@ -191,10 +201,46 @@ bool HciSocket::write(const uint8_t *pBuffer, size_t count) const return true; } +// Wait for data to arrive, or for a shutdown event +// +// Returns true if data is available, false if we are shutting down +bool HciSocket::waitForDataOrShutdown() const +{ + while(ggkIsServerRunning()) + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(fdSocket, &rfds); + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = kDataWaitTimeMS * 1000; + + int retval = select(fdSocket+1, &rfds, NULL, NULL, &tv); + + // Do we have data? + if (retval > 0) { return true; } + + // We have an error + if (retval < 0) { return false; } + + // No data; keep waiting + continue; + } + + return false; +} + // Utilitarian function for logging errors for the given operation void HciSocket::logErrno(const char *pOperation) const { - Logger::error(SSTR << "" << pOperation << " on Bluetooth management socket error (" << errno << "): " << strerror(errno)); + std::string errorDetail(strerror(errno)); + if (errno == EAGAIN) + { + errorDetail += " or not enough permission for this operation"; + } + + Logger::error(SSTR << "Error on Bluetooth management socket during " << pOperation << " operation. Error code " << errno << ": " << errorDetail); } }; // namespace ggk -- cgit v1.2.3