Logo Search packages:      
Sourcecode: kmess version File versions

ssdpconnection.cpp

/***************************************************************************
                          ssdpconnection.cpp -  description
                             -------------------
    begin                : Fri Jul 29 2005
    copyright            : (C) 2005 by Diederik van der Boor
    email                : vdboor --at-- codingdomain.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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "ssdpconnection.h"

#include <qhostaddress.h>
#include <qsocketdevice.h>
#include <qsocketnotifier.h>

#include <qcstring.h>

#include <kurl.h>

#include <kdebug.h>
#include "../../kmessdebug.h"

#ifdef KMESSDEBUG_UPNP
#define KMESSDEBUG_UPNP_GENERAL
#endif

namespace UPnP
{


// The constructor
SsdpConnection::SsdpConnection()
: QObject()
{
  // Create a UDP socket sending messages to a special broadcast address

  // Not using KExtendedSocket here, because it's: a. obsolete b. not documented well
  // In newer KDE versions we could use KNetwork::KDatagramSocket
  socket_ = new QSocketDevice(QSocketDevice::Datagram);

  notifier_ = new QSocketNotifier(socket_->socket(), QSocketNotifier::Read);
  connect(notifier_, SIGNAL( activated(int)       ) ,
          this,        SLOT( slotDataReceived()   ) );
}


// The destructor
SsdpConnection::~SsdpConnection()
{
  delete notifier_;
  if(socket_ != 0)
  {
    socket_->close();
    delete socket_;
  }
}



// Data was received by the socket
void SsdpConnection::slotDataReceived()
{
#ifdef KMESSDEBUG_UPNP_GENERAL
  kdDebug() << "UPnP::SsdpConnection: received " << socket_->bytesAvailable() << " bytes." << endl;
#endif

  // Get the HTTP-like content
  // TODO: How to handle multiple packets arriving from different devices?
  QByteArray response = socket_->readAll();

  // Response from my 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
  //

  QString sspdResponse = QString::fromUtf8(response.data(), response.size());

  // Find the location field manually, MimeMessage is not required
  int locationStart = sspdResponse.find("LOCATION:",0,false);   // case insensitive
  int locationEnd   = sspdResponse.find("\r\n",locationStart);

  locationStart    += 9;  // length of field name
  QString location  = sspdResponse.mid(locationStart, locationEnd - locationStart);

  // Parse the URL syntax using KURL
  KURL url(location);

  // Emit success
  emit deviceFound(url.host(), url.port(), url.path());
}


// Send a broadcast to detect all devices
void SsdpConnection::queryDevices(int bindPort)
{
#ifdef KMESSDEBUG_UPNP_GENERAL
  kdDebug() << "UPnP::SsdpConnection: Sending broadcast packet." << endl;
#endif

  // Send a packet to a broadcast address
  QHostAddress address;
  address.setAddress("239.255.255.250");

  QString data = "M-SEARCH * HTTP/1.1\r\n"
                 "Host:239.255.255.250:1900\r\n"
  //               "ST:upnp:rootdevice\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 = socket_->bind(QHostAddress(), bindPort);
  if(! success)
  {
    kdWarning() << "UPnP::SsdpConnection: Failed to bind to port " << bindPort << "." << endl;
  }

  // Send the data
  QCString dataBlock = data.utf8();
  int bytesWritten = socket_->writeBlock(dataBlock.data(), dataBlock.size(), address, 1900);

  if(bytesWritten == -1)
  {
    kdWarning() << "UPnP::SsdpConnection: Failed to send the UPnP broadcast packet." << endl;
  }
}



}  // end of namespace

#include "ssdpconnection.moc"

Generated by  Doxygen 1.6.0   Back to index