/************************************************************************* * Copyright (C) 2015 by Andrius Štikonas * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include #include #include #include #include #include "consolereader.h" #include "server.h" Server::Server ( std::vector *sockets_vector ) { sockets = sockets_vector; udpSocketGet = new QUdpSocket(); udpSocketGet->bind ( QHostAddress::Any, 10000 ); connect ( udpSocketGet, &QUdpSocket::readyRead, this, &Server::readPendingDatagrams); discoverSockets(); QTimer *discoverTimer = new QTimer(this); discoverTimer->setInterval(1*60*1000); // 1 min discoverTimer->setSingleShot(false); connect(discoverTimer, &QTimer::timeout, this, &Server::discoverSockets); discoverTimer->start(); start(); } Server::Server(uint16_t port, QByteArray ssid, QByteArray password) { QNetworkConfiguration *cfgInitial = new QNetworkConfiguration; QNetworkConfiguration *cfg = new QNetworkConfiguration; QNetworkConfigurationManager *ncm = new QNetworkConfigurationManager; ncm->updateConfigurations(); *cfgInitial = ncm->defaultConfiguration(); if (ssid == "c") { ssid = cfgInitial->name().toLocal8Bit(); qDebug() << "SSID unspecified, using current network: " << ssid; } bool stop = false; while ( !stop ) { QThread::sleep(1); auto nc = ncm->allConfigurations(); for (auto &x : nc) { if (x.bearerType() == QNetworkConfiguration::BearerWLAN) { if (x.name() == "WiWo-S20") { qWarning() << "Connecting to WiWo-S20 wireless"; cfg = &x; stop = true; } } } } QNetworkSession *session = new QNetworkSession(*cfg, this); session->open(); qWarning() << "Wait for connected!"; if (session->waitForOpened()) qWarning() << "Connected!"; QUdpSocket *udpSocketSend = new QUdpSocket(); udpSocketGet = new QUdpSocket(); udpSocketGet->bind ( QHostAddress::Any, port); QByteArray reply; udpSocketGet->writeDatagram ( QByteArray::fromStdString("HF-A11ASSISTHREAD"), QHostAddress::Broadcast, port ); reply = listen(QByteArray::fromStdString("HF-A11ASSISTHREAD")); QList list = reply.split(','); QHostAddress ip(QString::fromLatin1(list[0])); qWarning() << "IP: " << ip.toString(); udpSocketGet->writeDatagram ( QByteArray::fromStdString("+ok"), ip, port ); udpSocketGet->writeDatagram ( QByteArray::fromStdString("AT+WSSSID=") + ssid + QByteArray::fromStdString("\r"), ip, port ); listen(); udpSocketGet->writeDatagram ( QByteArray::fromStdString("AT+WSKEY=WPA2PSK,AES,") + password + QByteArray::fromStdString("\r"), ip, port ); // FIXME: support different security settings // OPEN, SHARED, WPAPSK......NONE, WEP, TKIP, AES listen(); udpSocketGet->writeDatagram ( QByteArray::fromStdString("AT+WMODE=STA\r"), ip, port ); listen(); udpSocketGet->writeDatagram ( QByteArray::fromStdString("AT+Z\r"), ip, port ); // reboot session->close(); // FIXME: discover the new socket qWarning() << "Finished"; session = new QNetworkSession(*cfgInitial, this); session->open(); if (session->waitForOpened()) qWarning() << "Connected"; discoverSockets(); } Server::~Server() { delete udpSocketGet; } QByteArray Server::listen(QByteArray message) { QByteArray reply; QHostAddress sender; quint16 senderPort; bool stop = false; while ( !stop ) { QThread::msleep(50); while ( udpSocketGet->hasPendingDatagrams() ) { reply.resize ( udpSocketGet->pendingDatagramSize() ); udpSocketGet->readDatagram ( reply.data(), reply.size(), &sender, &senderPort ); if (reply != message) { stop = true; } } } return reply; } void Server::run() { readPendingDatagrams(); } void Server::readPendingDatagrams() { while ( udpSocketGet->hasPendingDatagrams() ) { QByteArray reply, mac; reply.resize ( udpSocketGet->pendingDatagramSize() ); QHostAddress sender; quint16 senderPort; udpSocketGet->readDatagram ( reply.data(), reply.size(), &sender, &senderPort ); if ( reply != discover && reply.left ( 2 ) == magicKey ) // check for Magic Key { if ( reply.mid ( 4, 2 ) == QByteArray::fromHex ( "71 61" ) || reply.mid ( 4, 2 ) == QByteArray::fromHex ( "71 67" )) // Reply to discover packet { bool duplicate = false; for ( std::vector::const_iterator i = sockets->begin() ; i != sockets->end(); ++i ) { if ( (*i)->ip == sender ) { duplicate = true; break; } } if ( !duplicate ) { Socket *socket = new Socket ( sender, reply ); sockets->push_back ( socket ); Q_EMIT discovered(); } mac = reply.mid(7,6); } else { mac = reply.mid(6,6); } for ( std::vector::iterator i = sockets->begin() ; i != sockets->end(); ++i ) { if ( (*i)->mac == mac ) { (*i)->parseReply(reply); break; } } } } } void Server::discoverSockets() { QUdpSocket *udpSocketSend = new QUdpSocket(); udpSocketSend->connectToHost ( QHostAddress::Broadcast, 10000 ); udpSocketSend->write ( discover ); udpSocketSend->write ( discover ); udpSocketSend->disconnectFromHost(); delete udpSocketSend; } void broadcastPassword(QString password) { QUdpSocket *udpSocket = new QUdpSocket(); udpSocket->connectToHost ( QHostAddress::Broadcast, 49999 ); uint sleep = 15; for (uint j=0; j < 4; ++j) // FIXME: stopping loop on discovery { qWarning() << j; for (unsigned short int i = 0; i < 200; ++i) { udpSocket->write ( fives(76) ); QThread::msleep(sleep); } for (unsigned short int i = 0; i < 3; ++i) { udpSocket->write ( fives(89) ); QThread::msleep(sleep); } QChar *data = password.data(); while (!data->isNull()) { udpSocket->write( fives(data->unicode() + 76) ); QThread::msleep(sleep); ++data; } for (unsigned short int i = 0; i < 3; ++i) { udpSocket->write ( fives(86) ); QThread::msleep(sleep); } for (unsigned short int i = 0; i < 3; ++i) { udpSocket->write ( fives(332 + password.length()) ); QThread::msleep(sleep); } } udpSocket->disconnectFromHost(); delete udpSocket; // FIXME: special slightly modified SocketData packet might is needed here } QByteArray fives(unsigned short int length) { QByteArray packet; packet.fill(0x05, length); return packet; }