From 3d96b6e6e3f493b0f2c160aca73b412dc5d92d57 Mon Sep 17 00:00:00 2001 From: Cole Brinsfield Date: Sun, 20 Dec 2020 18:36:38 -0800 Subject: [PATCH] bluetooth handshake / wifi rework (#18) * Working on cleaning wifi * Reworked bluetooth handshake based around @presslab-us's work * Forgot to remove a line --- btservice/AndroidBluetoothServer.cpp | 220 +++++++++--------- btservice_proto/NetworkInfo.proto | 22 +- btservice_proto/PhoneResponse.proto | 8 - btservice_proto/SocketInfo.proto | 10 - btservice_proto/SocketInfoRequest.proto | 9 + btservice_proto/SocketInfoResponse.proto | 25 ++ include/btservice/AndroidBluetoothServer.hpp | 25 +- .../openauto/Configuration/Configuration.hpp | 4 + .../openauto/Configuration/IConfiguration.hpp | 2 + openauto/Configuration/Configuration.cpp | 13 ++ 10 files changed, 188 insertions(+), 150 deletions(-) delete mode 100644 btservice_proto/PhoneResponse.proto delete mode 100644 btservice_proto/SocketInfo.proto create mode 100644 btservice_proto/SocketInfoRequest.proto create mode 100644 btservice_proto/SocketInfoResponse.proto diff --git a/btservice/AndroidBluetoothServer.cpp b/btservice/AndroidBluetoothServer.cpp index 63647fe..c172815 100644 --- a/btservice/AndroidBluetoothServer.cpp +++ b/btservice/AndroidBluetoothServer.cpp @@ -12,44 +12,8 @@ AndroidBluetoothServer::AndroidBluetoothServer(openauto::configuration::IConfigu : rfcommServer_(std::make_unique(QBluetoothServiceInfo::RfcommProtocol, this)) , socket_(nullptr) , config_(std::move(config)) - , handshakeState_(ConnectionStatus::IDLE) { connect(rfcommServer_.get(), &QBluetoothServer::newConnection, this, &AndroidBluetoothServer::onClientConnected); - - auto* thread = QThread::create([&]{ this->eventLoop(); }); - thread->start(); -} - -void AndroidBluetoothServer::eventLoop() -{ - while(true) - { - switch(handshakeState_) - { - case ConnectionStatus::IDLE: - case ConnectionStatus::SENT_SOCKETINFO_MESSAGE: - case ConnectionStatus::SENT_NETWORKINFO_MESSAGE: - case ConnectionStatus::PHONE_RESP_NETWORKINFO: - case ConnectionStatus::ERROR: - break; - - case ConnectionStatus::DEVICE_CONNECTED: - handshakeState_ = ConnectionStatus::SENDING_SOCKETINFO_MESSAGE; - break; - - case ConnectionStatus::SENDING_SOCKETINFO_MESSAGE: - this->writeSocketInfoMessage(); - break; - - case ConnectionStatus::PHONE_RESP_SOCKETINFO: - handshakeState_ = ConnectionStatus::SENDING_NETWORKINFO_MESSAGE; - break; - - case ConnectionStatus::SENDING_NETWORKINFO_MESSAGE: - this->writeNetworkInfoMessage(); - break; - } - } } bool AndroidBluetoothServer::start(const QBluetoothAddress& address, uint16_t portNumber) @@ -65,7 +29,7 @@ void AndroidBluetoothServer::onClientConnected() { OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Device Connected: " << socket_->peerName().toStdString(); connect(socket_, SIGNAL(readyRead()), this, SLOT(readSocket())); - handshakeState_ = ConnectionStatus::DEVICE_CONNECTED; + writeSocketInfoRequest(); } else { @@ -90,9 +54,9 @@ bool AndroidBluetoothServer::writeProtoMessage(uint16_t messageType, google::pro return true; } -void AndroidBluetoothServer::writeSocketInfoMessage() +void AndroidBluetoothServer::writeSocketInfoRequest() { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending socket info."; + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending SocketInfoRequest."; QString ipAddr; foreach(QHostAddress addr, QNetworkInterface::allAddresses()) @@ -103,115 +67,147 @@ void AndroidBluetoothServer::writeSocketInfoMessage() } } - btservice::proto::SocketInfo socketInfo; - socketInfo.set_address(ipAddr.toStdString()); - socketInfo.set_port(5000); - socketInfo.set_unknown_1(0); + btservice::proto::SocketInfoRequest socketInfoRequest; + socketInfoRequest.set_ip_address(ipAddr.toStdString()); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] ipAddress: "<< ipAddr.toStdString(); - if(this->writeProtoMessage(7, socketInfo)) + socketInfoRequest.set_port(5000); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] port: "<< 5000; + + if(this->writeProtoMessage(1, socketInfoRequest)) { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent socket info."; - handshakeState_ = ConnectionStatus::SENT_SOCKETINFO_MESSAGE; + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent SocketInfoRequest."; } else { - OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending socket Info."; - handshakeState_ = ConnectionStatus::ERROR; + OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending SocketInfoRequest."; } } +void AndroidBluetoothServer::writeSocketInfoResponse() +{ + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending SocketInfoResponse."; + QString ipAddr; + foreach(QHostAddress addr, QNetworkInterface::allAddresses()) + { + if(!addr.isLoopback() && (addr.protocol() == QAbstractSocket::IPv4Protocol)) + { + ipAddr = addr.toString(); + } + } + + btservice::proto::SocketInfoResponse socketInfoResponse; + socketInfoResponse.set_ip_address(ipAddr.toStdString()); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] ipAddress: "<< ipAddr.toStdString(); + + socketInfoResponse.set_port(5000); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] port: "<< 5000; + + socketInfoResponse.set_status(btservice::proto::Status::STATUS_SUCCESS); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] status: "<< btservice::proto::Status::STATUS_SUCCESS; + + + if(this->writeProtoMessage(7, socketInfoResponse)) + { + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent SocketInfoResponse."; + } + else + { + OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending SocketInfoResponse."; + } +} + +void AndroidBluetoothServer::handleSocketInfoRequestResponse(QByteArray data) +{ + btservice::proto::SocketInfoResponse socketInfoResponse; + socketInfoResponse.ParseFromArray(data, data.size()); + OPENAUTO_LOG(info) <<"[AndroidBluetoothServer] Received SocketInfoRequestResponse, status: "<getWifiSSID()); - networkMessage.set_psk(config_->getWifiPassword()); - foreach(QNetworkInterface netInterface, QNetworkInterface::allInterfaces()) - { - // Return only the first non-loopback MAC Address - if (!(netInterface.flags() & QNetworkInterface::IsLoopBack)) - { - networkMessage.set_mac_addr(netInterface.hardwareAddress().toStdString()); - } - } - networkMessage.set_security_mode(8); - networkMessage.set_unknown_2(0); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] SSID: "<getWifiSSID(); - if(this->writeProtoMessage(3, networkMessage)) + networkMessage.set_psk(config_->getWifiPassword()); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] PSKEY: "<getWifiPassword(); + + if(config_->getWifiMAC().empty()) { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent network packet."; - handshakeState_ = ConnectionStatus::SENT_NETWORKINFO_MESSAGE; + networkMessage.set_mac_addr(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString()); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<getWifiMAC()); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<< config_->getWifiMAC(); } + + networkMessage.set_security_mode(btservice::proto::SecurityMode::WPA2_PERSONAL); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Security: "<< btservice::proto::SecurityMode::WPA2_PERSONAL; + + networkMessage.set_ap_type(btservice::proto::AccessPointType::STATIC); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] AP Type: "<< btservice::proto::AccessPointType::STATIC; + + + if(this->writeProtoMessage(3, networkMessage)) + { + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent NetworkInfoMessage"; + } + else + { + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending NetworkInfoMessage."; + } +} + +void AndroidBluetoothServer::handleUnknownMessage(int messageType, QByteArray data) +{ + OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Received unknown MessageType of "<read(1024); + auto data = socket_->readAll(); if(data.length() == 0) { return; } uint16_t messageType = (data[2] << 8) | data[3]; - btservice::proto::PhoneResponse resp; switch(messageType) { - case 2: - break; - - case 6: - resp.ParseFromString(data.toStdString().c_str()); - break; - } - - switch(handshakeState_) - { - case ConnectionStatus::IDLE: - case ConnectionStatus::DEVICE_CONNECTED: - case ConnectionStatus::SENDING_SOCKETINFO_MESSAGE: - case ConnectionStatus::PHONE_RESP_SOCKETINFO: - case ConnectionStatus::SENDING_NETWORKINFO_MESSAGE: - case ConnectionStatus::PHONE_RESP_NETWORKINFO: - case ConnectionStatus::ERROR: - break; - - case ConnectionStatus::SENT_SOCKETINFO_MESSAGE: - if(messageType == 2) - { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Phone acknowledged socket info."; - handshakeState_ = ConnectionStatus::PHONE_RESP_SOCKETINFO; - } - else - { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Got unexpected message."; - handshakeState_ = ConnectionStatus::ERROR; - } - break; - - case ConnectionStatus::SENT_NETWORKINFO_MESSAGE: - if(messageType == 6) - { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Phone acknowledged network info with status code: " << resp.status_code(); - handshakeState_ = ConnectionStatus::PHONE_RESP_NETWORKINFO; - } - else - { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Got unexpected message"; - handshakeState_ = ConnectionStatus::ERROR; - } - break; + case 1: + handleSocketInfoRequest(data); + break; + case 2: + writeNetworkInfoMessage(); + break; + case 7: + data.remove(0, 4); + handleSocketInfoRequestResponse(data); + break; + default: + data.remove(0, 4); + handleUnknownMessage(messageType, data); + break; } } diff --git a/btservice_proto/NetworkInfo.proto b/btservice_proto/NetworkInfo.proto index 5fe1416..c903f2a 100644 --- a/btservice_proto/NetworkInfo.proto +++ b/btservice_proto/NetworkInfo.proto @@ -2,11 +2,29 @@ syntax = "proto2"; package openauto.btservice.proto; +enum SecurityMode { + UNKNOWN_SECURITY_MODE = 0; + OPEN = 1; + WEP_64 = 2; + WEP_128 = 3; + WPA_PERSONAL = 4; + WPA2_PERSONAL = 8; + WPA_WPA2_PERSONAL = 12; + WPA_ENTERPRISE = 20; + WPA2_ENTERPRISE = 24; + WPA_WPA2_ENTERPRISE = 28; +} + +enum AccessPointType { + STATIC = 0; + DYNAMIC = 1; +} + message NetworkInfo { required string ssid = 1; required string psk = 2; required string mac_addr = 3; - required int32 security_mode = 4; - required int32 unknown_2 = 5; + required SecurityMode security_mode = 4; + required AccessPointType ap_type = 5; } diff --git a/btservice_proto/PhoneResponse.proto b/btservice_proto/PhoneResponse.proto deleted file mode 100644 index 25fdbd7..0000000 --- a/btservice_proto/PhoneResponse.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -package openauto.btservice.proto; - -message PhoneResponse -{ - int32 status_code = 1; -} diff --git a/btservice_proto/SocketInfo.proto b/btservice_proto/SocketInfo.proto deleted file mode 100644 index fe940fc..0000000 --- a/btservice_proto/SocketInfo.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto2"; - -package openauto.btservice.proto; - -message SocketInfo -{ - required string address = 1; - required int32 port = 2; - required int32 unknown_1 = 3; -} diff --git a/btservice_proto/SocketInfoRequest.proto b/btservice_proto/SocketInfoRequest.proto new file mode 100644 index 0000000..e8515e9 --- /dev/null +++ b/btservice_proto/SocketInfoRequest.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package openauto.btservice.proto; + +message SocketInfoRequest +{ + required string ip_address = 1; + optional uint32 port = 2; +} diff --git a/btservice_proto/SocketInfoResponse.proto b/btservice_proto/SocketInfoResponse.proto new file mode 100644 index 0000000..252d0fb --- /dev/null +++ b/btservice_proto/SocketInfoResponse.proto @@ -0,0 +1,25 @@ +syntax = "proto2"; + +package openauto.btservice.proto; + +enum Status { + STATUS_UNSOLICITED_MESSAGE = 1; + STATUS_SUCCESS = 0; + STATUS_NO_COMPATIBLE_VERSION = -1; + STATUS_WIFI_INACCESSIBLE_CHANNEL = -2; + STATUS_WIFI_INCORRECT_CREDENTIALS = -3; + STATUS_PROJECTION_ALREADY_STARTED = -4; + STATUS_WIFI_DISABLED = -5; + STATUS_WIFI_NOT_YET_STARTED = -6; + STATUS_INVALID_HOST = -7; + STATUS_NO_SUPPORTED_WIFI_CHANNELS = -8; + STATUS_INSTRUCT_USER_TO_CHECK_THE_PHONE = -9; + STATUS_PHONE_WIFI_DISABLED = -10; +} + +message SocketInfoResponse +{ + optional string ip_address = 1; + optional int32 port = 2; + required Status status = 3; +} diff --git a/include/btservice/AndroidBluetoothServer.hpp b/include/btservice/AndroidBluetoothServer.hpp index 07a2eca..d6d9d48 100644 --- a/include/btservice/AndroidBluetoothServer.hpp +++ b/include/btservice/AndroidBluetoothServer.hpp @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include "openauto/Configuration/Configuration.hpp" #include "IAndroidBluetoothServer.hpp" @@ -18,19 +18,6 @@ namespace openauto namespace btservice { -enum class ConnectionStatus -{ - IDLE, - DEVICE_CONNECTED, - SENDING_SOCKETINFO_MESSAGE, - SENT_SOCKETINFO_MESSAGE, - PHONE_RESP_SOCKETINFO, - SENDING_NETWORKINFO_MESSAGE, - SENT_NETWORKINFO_MESSAGE, - PHONE_RESP_NETWORKINFO, - ERROR -}; - class AndroidBluetoothServer: public QObject, public IAndroidBluetoothServer { Q_OBJECT @@ -47,11 +34,13 @@ private: std::unique_ptr rfcommServer_; QBluetoothSocket* socket_; openauto::configuration::IConfiguration::Pointer config_; - std::atomic handshakeState_; - void writeSocketInfoMessage(); + void handleUnknownMessage(int messageType, QByteArray data); + void handleSocketInfoRequest(QByteArray data); + void handleSocketInfoRequestResponse(QByteArray data); + void writeSocketInfoRequest(); + void writeSocketInfoResponse(); void writeNetworkInfoMessage(); - void eventLoop(); bool writeProtoMessage(uint16_t messageType, google::protobuf::Message& message); }; diff --git a/include/openauto/Configuration/Configuration.hpp b/include/openauto/Configuration/Configuration.hpp index 1bd4190..59b9299 100644 --- a/include/openauto/Configuration/Configuration.hpp +++ b/include/openauto/Configuration/Configuration.hpp @@ -72,6 +72,8 @@ public: void setWifiSSID(std::string value) override; std::string getWifiPassword() override; void setWifiPassword(std::string value) override; + std::string getWifiMAC() override; + void setWifiMAC(std::string value) override; private: void readButtonCodes(boost::property_tree::ptree& iniConfig); @@ -94,6 +96,7 @@ private: AudioOutputBackendType audioOutputBackendType_; std::string wifiSSID_; std::string wifiPassword_; + std::string wifiMAC_; static const std::string cConfigFileName; @@ -134,6 +137,7 @@ private: static const std::string cWifiSSID; static const std::string cWifiPskey; + static const std::string cWifiMAC; }; } diff --git a/include/openauto/Configuration/IConfiguration.hpp b/include/openauto/Configuration/IConfiguration.hpp index a4a20ec..413e9aa 100644 --- a/include/openauto/Configuration/IConfiguration.hpp +++ b/include/openauto/Configuration/IConfiguration.hpp @@ -81,6 +81,8 @@ public: virtual void setWifiSSID(std::string value) = 0; virtual std::string getWifiPassword() = 0; virtual void setWifiPassword(std::string value) = 0; + virtual std::string getWifiMAC() = 0; + virtual void setWifiMAC(std::string value) = 0; }; } diff --git a/openauto/Configuration/Configuration.cpp b/openauto/Configuration/Configuration.cpp index 472870c..d34db28 100644 --- a/openauto/Configuration/Configuration.cpp +++ b/openauto/Configuration/Configuration.cpp @@ -63,6 +63,7 @@ const std::string Configuration::cInputEnterButtonKey = "Input.EnterButton"; const std::string Configuration::cWifiSSID = "WiFi.SSID"; const std::string Configuration::cWifiPskey = "WiFi.Password"; +const std::string Configuration::cWifiMAC = "WiFi.AdapterMAC"; Configuration::Configuration() { @@ -105,6 +106,7 @@ void Configuration::load() wifiSSID_ = iniConfig.get(cWifiSSID, ""); wifiPassword_ = iniConfig.get(cWifiPskey, ""); + wifiMAC_ = iniConfig.get(cWifiMAC, ""); } catch(const boost::property_tree::ini_parser_error& e) { @@ -158,6 +160,7 @@ void Configuration::save() iniConfig.put(cWifiSSID, wifiSSID_); iniConfig.put(cWifiPskey, wifiPassword_); + iniConfig.put(cWifiMAC, wifiMAC_); boost::property_tree::ini_parser::write_ini(cConfigFileName, iniConfig); } @@ -321,6 +324,16 @@ void Configuration::setWifiPassword(std::string value) wifiPassword_ = value; } +std::string Configuration::getWifiMAC() +{ + return wifiMAC_; +} + +void Configuration::setWifiMAC(std::string value) +{ + wifiMAC_ = value; +} + void Configuration::readButtonCodes(boost::property_tree::ptree& iniConfig) { this->insertButtonCode(iniConfig, cInputPlayButtonKey, aasdk::proto::enums::ButtonCode::PLAY);