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))
, 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: "<<socketInfoResponse.status();
}
void AndroidBluetoothServer::handleSocketInfoRequest(QByteArray data)
{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Reading SocketInfoRequest.";
btservice::proto::SocketInfoRequest socketInfoRequest;
writeSocketInfoResponse();
}
void AndroidBluetoothServer::writeNetworkInfoMessage()
{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending network packet.";
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending NetworkInfoMessage.";
btservice::proto::NetworkInfo networkMessage;
networkMessage.set_ssid(config_->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: "<<config_->getWifiSSID();
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.";
handshakeState_ = ConnectionStatus::SENT_NETWORKINFO_MESSAGE;
networkMessage.set_mac_addr(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString());
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] MAC: "<<QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString();
}
else
{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending network packet.";
handshakeState_ = ConnectionStatus::ERROR;
networkMessage.set_mac_addr(config_->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 "<<messageType;
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Unknown Message Data: "<<data.toHex(' ').toStdString() ;
}
void AndroidBluetoothServer::readSocket()
{
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] DATA: ";
if(!socket_)
{
return;
}
auto data = socket_->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;
}
}

View File

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

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 <QDataStream>
#include <btservice_proto/NetworkInfo.pb.h>
#include <btservice_proto/PhoneResponse.pb.h>
#include <btservice_proto/SocketInfo.pb.h>
#include <btservice_proto/SocketInfoRequest.pb.h>
#include <btservice_proto/SocketInfoResponse.pb.h>
#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<QBluetoothServer> rfcommServer_;
QBluetoothSocket* socket_;
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 eventLoop();
bool writeProtoMessage(uint16_t messageType, google::protobuf::Message& message);
};

View File

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

View File

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

View File

@ -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<std::string>(cWifiSSID, "");
wifiPassword_ = iniConfig.get<std::string>(cWifiPskey, "");
wifiMAC_ = iniConfig.get<std::string>(cWifiMAC, "");
}
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>(cWifiPskey, wifiPassword_);
iniConfig.put<std::string>(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);