//=============================================================================
//
// File : SsdpConnection.cpp
// Creation date : Fri Aug 08 18:00:00 2008 GMT by Fabio Bas
//
// This file is part of the KVIrc IRC client distribution
// Copyright (C) 2008 Fabio Bas (ctrlaltca at gmail dot com)
//
// 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 2
// 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, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// Original Copyright follows:
//=============================================================================
/***************************************************************************
SsdpConnection.cpp - description
-------------------
begin : Fri Jul 29 2005
copyright : (C) 2005 by Diederik van der Boor
email : vdboor --at-- codingdomain.com
***************************************************************************/
#include "SsdpConnection.h"
#include <QHostAddress>
#include <QUdpSocket>
#include <QByteArray>
#include <QDebug>
#include <QUrl>
namespace UPnP
{
SsdpConnection::SsdpConnection()
: QObject()
{
m_pSocket = new QUdpSocket();
connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(slotDataReceived()));
}
SsdpConnection::~SsdpConnection()
{
if(m_pSocket != nullptr)
{
m_pSocket->close();
delete m_pSocket;
}
}
// Data was received by the socket
void SsdpConnection::slotDataReceived()
{
qDebug() << "UPnP::SsdpConnection: received " << m_pSocket->bytesAvailable() << " bytes." << Qt::endl;
// Response from Diederik's Acatel router:
//
// HTTP/1.1 200 OK
// CACHE-CONTROL:max-age=1800
// EXT:
// LOCATION:http://10.0.0.138:80/IGD.xml
// SERVER:SpeedTouch 510 4.0.2.0.0 UPnP/1.0 (0313QZ6S2)
// ST:upnp:rootdevice
// USN:uuid:UPnP-SpeedTouch510-1_00-90-D0-8E-A1-6F::upnp:rootdevice
//
// This is from a Zyxel router:
//
// HTTP/1.1 200 OK
// ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1
// USN:uuid:11111111-%04x-c0a8-fcb30002cf618c::urn:schemas-upnp-org:device:InternetGatewayDevice:1
// Location:http://192.168.252.179:80/DeviceDescription.xml
// Cache-Control: max-age=480
// Server: ZyXEL-RomPlug/4.51 UPnP/1.0 IGD/1.00
// Ext:
while(m_pSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(m_pSocket->pendingDatagramSize());
m_pSocket->readDatagram(datagram.data(), datagram.size());
qDebug("Received datagram: %s\n", datagram.data());
QString sspdResponse = QString::fromUtf8(datagram.data(), datagram.size());
// Find the location field manually, MimeMessage is not required
int locationStart = sspdResponse.indexOf("LOCATION:", 0, Qt::CaseInsensitive);
int locationEnd = sspdResponse.indexOf("\r\n", locationStart, Qt::CaseSensitive);
locationStart += 9; // length of field name
QString location = sspdResponse.mid(locationStart, locationEnd - locationStart);
// Parse the URL syntax using KURL
QUrl url(location.trimmed());
qDebug("Found internet gateway: %s\n", location.toUtf8().data());
// Emit success
emit deviceFound(url.host(), url.port(), url.path());
}
}
// Send a broadcast to detect all devices
void SsdpConnection::queryDevices(int bindPort)
{
qDebug() << "UPnP::SsdpConnection: sending broadcast packet." << Qt::endl;
// Send a packet to a broadcast address
QHostAddress address("239.255.255.250");
QString data = "M-SEARCH * HTTP/1.1\r\n"
"Host:239.255.255.250:1900\r\n"
"ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n"
"Man:\"ssdp:discover\"\r\n"
"MX:3\r\n"
"\r\n";
// Bind the socket to a certain port
bool success = m_pSocket->bind(bindPort);
if(!success)
{
qDebug() << "UPnP::SsdpConnection: failed to bind to port " << bindPort << "." << Qt::endl;
}
// Send the data
QByteArray dataBlock = data.toUtf8();
int bytesWritten = m_pSocket->writeDatagram(dataBlock.data(), dataBlock.size(), address, 1900);
if(bytesWritten == -1)
{
qDebug() << "UPnP::SsdpConnection: failed to send the UPnP broadcast packet." << Qt::endl;
}
}
} // end of namespace