bluetooth handshake / wifi rework (#18)

* Working on cleaning wifi

* Reworked bluetooth handshake based around @presslab-us's work

* Forgot to remove a line
This commit is contained in:
Cole Brinsfield 2020-12-20 18:36:38 -08:00 committed by GitHub
parent 88833fb5db
commit 3d96b6e6e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 188 additions and 150 deletions

View File

@ -12,44 +12,8 @@ AndroidBluetoothServer::AndroidBluetoothServer(openauto::configuration::IConfigu
: rfcommServer_(std::make_unique<QBluetoothServer>(QBluetoothServiceInfo::RfcommProtocol, this)) : rfcommServer_(std::make_unique<QBluetoothServer>(QBluetoothServiceInfo::RfcommProtocol, this))
, socket_(nullptr) , socket_(nullptr)
, config_(std::move(config)) , config_(std::move(config))
, handshakeState_(ConnectionStatus::IDLE)
{ {
connect(rfcommServer_.get(), &QBluetoothServer::newConnection, this, &AndroidBluetoothServer::onClientConnected); 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) 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(); OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Device Connected: " << socket_->peerName().toStdString();
connect(socket_, SIGNAL(readyRead()), this, SLOT(readSocket())); connect(socket_, SIGNAL(readyRead()), this, SLOT(readSocket()));
handshakeState_ = ConnectionStatus::DEVICE_CONNECTED; writeSocketInfoRequest();
} }
else else
{ {
@ -90,9 +54,9 @@ bool AndroidBluetoothServer::writeProtoMessage(uint16_t messageType, google::pro
return true; return true;
} }
void AndroidBluetoothServer::writeSocketInfoMessage() void AndroidBluetoothServer::writeSocketInfoRequest()
{ {
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending socket info."; OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending SocketInfoRequest.";
QString ipAddr; QString ipAddr;
foreach(QHostAddress addr, QNetworkInterface::allAddresses()) foreach(QHostAddress addr, QNetworkInterface::allAddresses())
@ -103,114 +67,146 @@ void AndroidBluetoothServer::writeSocketInfoMessage()
} }
} }
btservice::proto::SocketInfo socketInfo; btservice::proto::SocketInfoRequest socketInfoRequest;
socketInfo.set_address(ipAddr.toStdString()); socketInfoRequest.set_ip_address(ipAddr.toStdString());
socketInfo.set_port(5000); OPENAUTO_LOG(info) << "[AndroidBluetoothServer] ipAddress: "<< ipAddr.toStdString();
socketInfo.set_unknown_1(0);
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."; OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent SocketInfoRequest.";
handshakeState_ = ConnectionStatus::SENT_SOCKETINFO_MESSAGE;
} }
else else
{ {
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending socket Info."; OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending SocketInfoRequest.";
handshakeState_ = ConnectionStatus::ERROR;
} }
} }
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: "<<socketInfoResponse.status();
}
void AndroidBluetoothServer::handleSocketInfoRequest(QByteArray data)
{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Reading SocketInfoRequest.";
btservice::proto::SocketInfoRequest socketInfoRequest;
writeSocketInfoResponse();
}
void AndroidBluetoothServer::writeNetworkInfoMessage() void AndroidBluetoothServer::writeNetworkInfoMessage()
{ {
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending network packet."; OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending NetworkInfoMessage.";
btservice::proto::NetworkInfo networkMessage; btservice::proto::NetworkInfo networkMessage;
networkMessage.set_ssid(config_->getWifiSSID()); networkMessage.set_ssid(config_->getWifiSSID());
networkMessage.set_psk(config_->getWifiPassword()); OPENAUTO_LOG(info) << "[AndroidBluetoothServer] SSID: "<<config_->getWifiSSID();
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);
if(this->writeProtoMessage(3, networkMessage)) networkMessage.set_psk(config_->getWifiPassword());
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] PSKEY: "<<config_->getWifiPassword();
if(config_->getWifiMAC().empty())
{ {
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent network packet."; networkMessage.set_mac_addr(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString());
handshakeState_ = ConnectionStatus::SENT_NETWORKINFO_MESSAGE; OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<<QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString();
} }
else else
{ {
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending network packet."; networkMessage.set_mac_addr(config_->getWifiMAC());
handshakeState_ = ConnectionStatus::ERROR; 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 "<<messageType;
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Unknown Message Data: "<<data.toHex(' ').toStdString() ;
} }
void AndroidBluetoothServer::readSocket() void AndroidBluetoothServer::readSocket()
{ {
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] DATA: ";
if(!socket_) if(!socket_)
{ {
return; return;
} }
auto data = socket_->read(1024); auto data = socket_->readAll();
if(data.length() == 0) if(data.length() == 0)
{ {
return; return;
} }
uint16_t messageType = (data[2] << 8) | data[3]; uint16_t messageType = (data[2] << 8) | data[3];
btservice::proto::PhoneResponse resp;
switch(messageType) switch(messageType)
{ {
case 1:
handleSocketInfoRequest(data);
break;
case 2: case 2:
writeNetworkInfoMessage();
break; break;
case 7:
case 6: data.remove(0, 4);
resp.ParseFromString(data.toStdString().c_str()); handleSocketInfoRequestResponse(data);
break; break;
} default:
data.remove(0, 4);
switch(handshakeState_) handleUnknownMessage(messageType, data);
{
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; break;
} }
} }

View File

@ -2,11 +2,29 @@ syntax = "proto2";
package openauto.btservice.proto; 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 message NetworkInfo
{ {
required string ssid = 1; required string ssid = 1;
required string psk = 2; required string psk = 2;
required string mac_addr = 3; required string mac_addr = 3;
required int32 security_mode = 4; required SecurityMode security_mode = 4;
required int32 unknown_2 = 5; required AccessPointType ap_type = 5;
} }

View File

@ -1,8 +0,0 @@
syntax = "proto3";
package openauto.btservice.proto;
message PhoneResponse
{
int32 status_code = 1;
}

View File

@ -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;
}

View File

@ -0,0 +1,9 @@
syntax = "proto2";
package openauto.btservice.proto;
message SocketInfoRequest
{
required string ip_address = 1;
optional uint32 port = 2;
}

View File

@ -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;
}

View File

@ -8,8 +8,8 @@
#include <QBluetoothLocalDevice> #include <QBluetoothLocalDevice>
#include <QDataStream> #include <QDataStream>
#include <btservice_proto/NetworkInfo.pb.h> #include <btservice_proto/NetworkInfo.pb.h>
#include <btservice_proto/PhoneResponse.pb.h> #include <btservice_proto/SocketInfoRequest.pb.h>
#include <btservice_proto/SocketInfo.pb.h> #include <btservice_proto/SocketInfoResponse.pb.h>
#include "openauto/Configuration/Configuration.hpp" #include "openauto/Configuration/Configuration.hpp"
#include "IAndroidBluetoothServer.hpp" #include "IAndroidBluetoothServer.hpp"
@ -18,19 +18,6 @@ namespace openauto
namespace btservice 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 class AndroidBluetoothServer: public QObject, public IAndroidBluetoothServer
{ {
Q_OBJECT Q_OBJECT
@ -47,11 +34,13 @@ private:
std::unique_ptr<QBluetoothServer> rfcommServer_; std::unique_ptr<QBluetoothServer> rfcommServer_;
QBluetoothSocket* socket_; QBluetoothSocket* socket_;
openauto::configuration::IConfiguration::Pointer config_; openauto::configuration::IConfiguration::Pointer config_;
std::atomic<ConnectionStatus> handshakeState_;
void writeSocketInfoMessage(); void handleUnknownMessage(int messageType, QByteArray data);
void handleSocketInfoRequest(QByteArray data);
void handleSocketInfoRequestResponse(QByteArray data);
void writeSocketInfoRequest();
void writeSocketInfoResponse();
void writeNetworkInfoMessage(); void writeNetworkInfoMessage();
void eventLoop();
bool writeProtoMessage(uint16_t messageType, google::protobuf::Message& message); bool writeProtoMessage(uint16_t messageType, google::protobuf::Message& message);
}; };

View File

@ -72,6 +72,8 @@ public:
void setWifiSSID(std::string value) override; void setWifiSSID(std::string value) override;
std::string getWifiPassword() override; std::string getWifiPassword() override;
void setWifiPassword(std::string value) override; void setWifiPassword(std::string value) override;
std::string getWifiMAC() override;
void setWifiMAC(std::string value) override;
private: private:
void readButtonCodes(boost::property_tree::ptree& iniConfig); void readButtonCodes(boost::property_tree::ptree& iniConfig);
@ -94,6 +96,7 @@ private:
AudioOutputBackendType audioOutputBackendType_; AudioOutputBackendType audioOutputBackendType_;
std::string wifiSSID_; std::string wifiSSID_;
std::string wifiPassword_; std::string wifiPassword_;
std::string wifiMAC_;
static const std::string cConfigFileName; static const std::string cConfigFileName;
@ -134,6 +137,7 @@ private:
static const std::string cWifiSSID; static const std::string cWifiSSID;
static const std::string cWifiPskey; static const std::string cWifiPskey;
static const std::string cWifiMAC;
}; };
} }

View File

@ -81,6 +81,8 @@ public:
virtual void setWifiSSID(std::string value) = 0; virtual void setWifiSSID(std::string value) = 0;
virtual std::string getWifiPassword() = 0; virtual std::string getWifiPassword() = 0;
virtual void setWifiPassword(std::string value) = 0; virtual void setWifiPassword(std::string value) = 0;
virtual std::string getWifiMAC() = 0;
virtual void setWifiMAC(std::string value) = 0;
}; };
} }

View File

@ -63,6 +63,7 @@ const std::string Configuration::cInputEnterButtonKey = "Input.EnterButton";
const std::string Configuration::cWifiSSID = "WiFi.SSID"; const std::string Configuration::cWifiSSID = "WiFi.SSID";
const std::string Configuration::cWifiPskey = "WiFi.Password"; const std::string Configuration::cWifiPskey = "WiFi.Password";
const std::string Configuration::cWifiMAC = "WiFi.AdapterMAC";
Configuration::Configuration() Configuration::Configuration()
{ {
@ -105,6 +106,7 @@ void Configuration::load()
wifiSSID_ = iniConfig.get<std::string>(cWifiSSID, ""); wifiSSID_ = iniConfig.get<std::string>(cWifiSSID, "");
wifiPassword_ = iniConfig.get<std::string>(cWifiPskey, ""); wifiPassword_ = iniConfig.get<std::string>(cWifiPskey, "");
wifiMAC_ = iniConfig.get<std::string>(cWifiMAC, "");
} }
catch(const boost::property_tree::ini_parser_error& e) catch(const boost::property_tree::ini_parser_error& e)
{ {
@ -158,6 +160,7 @@ void Configuration::save()
iniConfig.put<std::string>(cWifiSSID, wifiSSID_); iniConfig.put<std::string>(cWifiSSID, wifiSSID_);
iniConfig.put<std::string>(cWifiPskey, wifiPassword_); iniConfig.put<std::string>(cWifiPskey, wifiPassword_);
iniConfig.put<std::string>(cWifiMAC, wifiMAC_);
boost::property_tree::ini_parser::write_ini(cConfigFileName, iniConfig); boost::property_tree::ini_parser::write_ini(cConfigFileName, iniConfig);
} }
@ -321,6 +324,16 @@ void Configuration::setWifiPassword(std::string value)
wifiPassword_ = 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) void Configuration::readButtonCodes(boost::property_tree::ptree& iniConfig)
{ {
this->insertButtonCode(iniConfig, cInputPlayButtonKey, aasdk::proto::enums::ButtonCode::PLAY); this->insertButtonCode(iniConfig, cInputPlayButtonKey, aasdk::proto::enums::ButtonCode::PLAY);