//============================================================================= // // 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 #include #include #include #include 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