* initial cleanup passthrough * bad copypaste * add back ! and more style fixes * handling ping and voice session
220 lines
6.6 KiB
C++
220 lines
6.6 KiB
C++
#include <QNetworkInterface>
|
|
#include <QThread>
|
|
#include "OpenautoLog.hpp"
|
|
#include "btservice/AndroidBluetoothServer.hpp"
|
|
|
|
namespace openauto
|
|
{
|
|
namespace btservice
|
|
{
|
|
|
|
AndroidBluetoothServer::AndroidBluetoothServer(openauto::configuration::IConfiguration::Pointer config)
|
|
: 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)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] listening.";
|
|
return rfcommServer_->listen(address, portNumber);
|
|
}
|
|
|
|
void AndroidBluetoothServer::onClientConnected()
|
|
{
|
|
socket_ = rfcommServer_->nextPendingConnection();
|
|
if(socket_ != nullptr)
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Device Connected: " << socket_->peerName().toStdString();
|
|
connect(socket_, SIGNAL(readyRead()), this, SLOT(readSocket()));
|
|
handshakeState_ = ConnectionStatus::DEVICE_CONNECTED;
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] received null socket during client connection.";
|
|
}
|
|
}
|
|
|
|
bool AndroidBluetoothServer::writeProtoMessage(uint16_t messageType, google::protobuf::Message& message)
|
|
{
|
|
QByteArray byteArray(message.SerializeAsString().c_str(), message.ByteSize());
|
|
uint16_t messageLength = message.ByteSize();
|
|
byteArray.prepend(messageType & 0x000000ff);
|
|
byteArray.prepend((messageType & 0x0000ff00) >> 8);
|
|
byteArray.prepend(messageLength & 0x000000ff);
|
|
byteArray.prepend((messageLength & 0x0000ff00) >> 8);
|
|
|
|
if(socket_->write(byteArray) != byteArray.length())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AndroidBluetoothServer::writeSocketInfoMessage()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending socket info.";
|
|
|
|
QString ipAddr;
|
|
foreach(QHostAddress addr, QNetworkInterface::allAddresses())
|
|
{
|
|
if(!addr.isLoopback() && (addr.protocol() == QAbstractSocket::IPv4Protocol))
|
|
{
|
|
ipAddr = addr.toString();
|
|
}
|
|
}
|
|
|
|
btservice::proto::SocketInfo socketInfo;
|
|
socketInfo.set_address(ipAddr.toStdString());
|
|
socketInfo.set_port(5000);
|
|
socketInfo.set_unknown_1(0);
|
|
|
|
if(this->writeProtoMessage(7, socketInfo))
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent socket info.";
|
|
handshakeState_ = ConnectionStatus::SENT_SOCKETINFO_MESSAGE;
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(error) << "[AndroidBluetoothServer] Error sending socket Info.";
|
|
handshakeState_ = ConnectionStatus::ERROR;
|
|
}
|
|
}
|
|
|
|
void AndroidBluetoothServer::writeNetworkInfoMessage()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sending network packet.";
|
|
|
|
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);
|
|
|
|
if(this->writeProtoMessage(3, networkMessage))
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Sent network packet.";
|
|
handshakeState_ = ConnectionStatus::SENT_NETWORKINFO_MESSAGE;
|
|
}
|
|
else
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] Error sending network packet.";
|
|
handshakeState_ = ConnectionStatus::ERROR;
|
|
}
|
|
}
|
|
|
|
void AndroidBluetoothServer::readSocket()
|
|
{
|
|
OPENAUTO_LOG(info) << "[AndroidBluetoothServer] DATA: ";
|
|
if(!socket_)
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto data = socket_->read(1024);
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|