Jelajahi Sumber

Fix Bluetooth Ping Timeout

JDierkse 6 tahun lalu
induk
melakukan
b623ba5003
5 mengubah file dengan 106 tambahan dan 80 penghapusan
  1. 24 39
      Bluetooth/Device.cpp
  2. 1 0
      Bluetooth/Device.h
  3. 50 2
      Bluetooth/Functions.cpp
  4. 30 39
      UniFi/Device.cpp
  5. 1 0
      UniFi/Device.h

+ 24 - 39
Bluetooth/Device.cpp

@@ -45,58 +45,43 @@ void Device::UpdatePresentDevices()
 		if (Functions::Ping(*it))
 		{
 			if (std::find(m_presentDevices.begin(), m_presentDevices.end(), *it) == m_presentDevices.end())
-				addedDevices.push_back(*it);
+				SendStateChange(true, *it);
 			presentDevices.push_back(*it);
 		}
 	}
 
 	for (std::vector<std::string>::iterator it = m_presentDevices.begin(); it != m_presentDevices.end(); ++it)
 		if (std::find(presentDevices.begin(), presentDevices.end(), *it) == presentDevices.end())
-			removedDevices.push_back(*it);
+			SendStateChange(false, *it);
 
-	for (std::vector<std::string>::iterator it = addedDevices.begin(); it != addedDevices.end(); ++it)
-	{
-		std::stringstream ss;
-		ss << "Bluetooth: + " << *it;
-		syslog(LOG_INFO, "%s", ss.str().c_str());
+	m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
+}
 
-		std::stringstream url;
-		url << m_target << "/Bluetooth/+/" << *it;
+void Device::SendStateChange(bool present, const std::string& macAddress)
+{
+	char sign;
+	if (present)
+		sign = '+';
+	else
+		sign = '-';
 
-		try
-		{
-			m_httpClient.GetUrlSilent(url.str());
-		}
-		catch (const std::exception& e)
-		{
-			std::stringstream ss;
-			ss << "BluetoothDevice::UpdatePresentDevices() - Error: " << e.what() << std::endl;
-			syslog(LOG_ERR, "%s", ss.str().c_str());
-		}
-	}
+	std::stringstream ss;
+	ss << "Bluetooth: " << sign << " " << macAddress;
+	syslog(LOG_INFO, "%s", ss.str().c_str());
+
+	std::stringstream url;
+	url << m_target << "/Bluetooth/" << sign << "/" << macAddress;
 
-	for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
+	try
+	{
+		m_httpClient.GetUrlSilent(url.str());
+	}
+	catch (const std::exception& e)
 	{
 		std::stringstream ss;
-		ss << "Bluetooth: - " << *it;
-		syslog(LOG_INFO, "%s", ss.str().c_str());
-
-		std::stringstream url;
-		url << m_target << "/Bluetooth/-/" << *it;
-
-		try
-		{
-			m_httpClient.GetUrlSilent(url.str());
-		}
-		catch (const std::exception& e)
-		{
-			std::stringstream ss;
-			ss << "BluetoothDevice::UpdatePresentDevices() - Error: " << e.what() << std::endl;
-			syslog(LOG_ERR, "%s", ss.str().c_str());
-		}
+		ss << "Bluetooth::Device::SendStateChange() - Error: " << e.what() << std::endl;
+		syslog(LOG_ERR, "%s", ss.str().c_str());
 	}
-
-	m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
 }
 
 } // namespace Bluetooth

+ 1 - 0
Bluetooth/Device.h

@@ -22,6 +22,7 @@ public:
 
 private:
 	void UpdatePresentDevices();
+	void SendStateChange(bool present, const std::string& macAddress);
 
 private:
 	Util::Timer m_timer;

+ 50 - 2
Bluetooth/Functions.cpp

@@ -6,6 +6,7 @@
 #include <bluetooth/hci.h>
 #include <bluetooth/l2cap.h>
 
+#include <fcntl.h>
 #include <unistd.h>
 #include <sys/poll.h>
 #include "Socket.h"
@@ -42,8 +43,55 @@ bool Functions::Ping(const std::string& macAddress)
 	socketAddress.l2_family = AF_BLUETOOTH;
 	str2ba(macAddress.c_str(), &socketAddress.l2_bdaddr);
 
-	if (connect(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress)) < 0)
-		return false;
+	struct timeval timeoutStruct;
+	timeoutStruct.tv_sec = 3;
+	timeoutStruct.tv_usec = 0;
+
+	fd_set writeDescriptor, errorDescriptor;
+	FD_ZERO(&writeDescriptor);
+	FD_ZERO(&errorDescriptor);
+	FD_SET(socketDescriptor, &writeDescriptor);
+	FD_SET(socketDescriptor, &errorDescriptor);
+
+	int flags;
+	if((flags = fcntl(socketDescriptor, F_GETFL, 0) < 0))
+		throw std::runtime_error("Can't get socket options");
+
+	if(fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) < 0)
+		throw std::runtime_error("Can't set socket options");
+
+	int ret = 0;
+	if ((ret = connect(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress)) < 0))
+	{
+		if (errno != EINPROGRESS)
+			return false;
+	}
+
+	if (ret != 0)
+	{
+		if (select(socketDescriptor + 1, &errorDescriptor, &writeDescriptor, NULL, &timeoutStruct) < 0)
+			return false;
+
+		int error = 0;
+		socklen_t len = sizeof(error);
+		if (FD_ISSET(socketDescriptor, &errorDescriptor) || FD_ISSET(socketDescriptor, &writeDescriptor))
+		{
+			if (getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+				return false;
+		}
+		else
+		{
+			return false;
+		}
+
+		if (error)
+			return false;
+	}
+
+	if(fcntl(socketDescriptor, F_SETFL, flags) < 0)
+		throw std::runtime_error("Can't set socket options");
+
+	connect(socketDescriptor, reinterpret_cast<struct sockaddr*>(&socketAddress), sizeof(socketAddress));
 
 	memset(&socketAddress, 0, sizeof(socketAddress));
 	socklen_t optlen = sizeof(socketAddress);

+ 30 - 39
UniFi/Device.cpp

@@ -71,7 +71,7 @@ bool Device::Login()
 	catch (const std::exception& e)
 	{
 		std::stringstream ss;
-		ss << "UniFiDevice::Login() - Error: " << e.what() << std::endl;
+		ss << "UniFi::Device::Login() - Error: " << e.what() << std::endl;
 		syslog(LOG_ERR, "%s", ss.str().c_str());
 		std::lock_guard<std::mutex> lock(m_mutex);
 		m_loggedIn = false;
@@ -98,7 +98,7 @@ void Device::Logout()
 	catch (const std::exception& e)
 	{
 		std::stringstream ss;
-		ss << "UniFiDevice::Logout() - Error: " << e.what() << std::endl;
+		ss << "UniFi::Device::Logout() - Error: " << e.what() << std::endl;
 		syslog(LOG_ERR, "%s", ss.str().c_str());
 	}
 }
@@ -156,7 +156,7 @@ void Device::UpdatePresentDevices()
 	catch (const std::exception& e)
 	{
 		std::stringstream ss;
-		ss << "UniFiDevice::IsDevicePresent() - Error: " << e.what() << std::endl;
+		ss << "UniFi::Device::IsDevicePresent() - Error: " << e.what() << std::endl;
 		syslog(LOG_ERR, "%s", ss.str().c_str());
 		Logout();
 		return;
@@ -167,48 +167,39 @@ void Device::UpdatePresentDevices()
 			removedDevices.push_back(*it);
 
 	for (std::vector<std::string>::iterator it = addedDevices.begin(); it != addedDevices.end(); ++it)
-	{
-		std::stringstream ss;
-		ss << "UniFi: + " << *it;
-		syslog(LOG_INFO, "%s", ss.str().c_str());
+		SendStateChange(true, *it);
 
-		std::stringstream url;
-		url << m_target << "/UniFi/+/" << *it;
+	for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
+		SendStateChange(false, *it);
 
-		try
-		{
-			m_httpClient.GetUrlSilent(url.str());
-		}
-		catch (const std::exception& e)
-		{
-			std::stringstream ss;
-			ss << "UniFiDevice::UpdatePresentDevices() - Error: " << e.what() << std::endl;
-			syslog(LOG_ERR, "%s", ss.str().c_str());
-		}
-	}
+	m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
+}
 
-	for (std::vector<std::string>::iterator it = removedDevices.begin(); it != removedDevices.end(); ++it)
-	{
-		std::stringstream ss;
-		ss << "UniFi: - " << *it;
-		syslog(LOG_INFO, "%s", ss.str().c_str());
+void Device::SendStateChange(bool present, const std::string& macAddress)
+{
+	char sign;
+	if (present)
+		sign = '+';
+	else
+		sign = '-';
 
-		std::stringstream url;
-		url << m_target << "/UniFi/-/" << *it;
+	std::stringstream ss;
+	ss << "UniFi: " << sign << " " << macAddress;
+	syslog(LOG_INFO, "%s", ss.str().c_str());
 
-		try
-		{
-			m_httpClient.GetUrlSilent(url.str());
-		}
-		catch (const std::exception& e)
-		{
-			std::stringstream ss;
-			ss << "UniFiDevice::UpdatePresentDevices() - Error: " << e.what() << std::endl;
-			syslog(LOG_ERR, "%s", ss.str().c_str());
-		}
-	}
+	std::stringstream url;
+	url << m_target << "/UniFi/" << sign << "/" << macAddress;
 
-	m_presentDevices.assign(presentDevices.begin(), presentDevices.end());
+	try
+	{
+		m_httpClient.GetUrlSilent(url.str());
+	}
+	catch (const std::exception& e)
+	{
+		std::stringstream ss;
+		ss << "UniFi::Device::SendStateChange() - Error: " << e.what() << std::endl;
+		syslog(LOG_ERR, "%s", ss.str().c_str());
+	}
 }
 
 } // namespace UniFi

+ 1 - 0
UniFi/Device.h

@@ -26,6 +26,7 @@ private:
 	void Logout();
 
 	void UpdatePresentDevices();
+	void SendStateChange(bool present, const std::string& macAddress);
 
 private:
 	Util::Timer m_timer;