Skip to content

Commit

Permalink
This ports a few UPnP changes over from mythtv-rec2.
Browse files Browse the repository at this point in the history
 * SSDPCacheEntries::Find() and SSDPCacheEntries::GetFirst() now return a locked device location (when non-null)
    This ensures that there are no race conditions wrt to disappearing devices. Of all the changes
    this is most likely to cause problems to UPnP code outside the tree.
 * Many classes now have a toString() for debugging.
 * Extends SOAPClient so it can send different commands; this is not used yet in master, but is used in mythtv-rec2 to communicate with an OCUR recording device.
 * Moves UPnpServiceImpl class into it's own files.
 * Moves MBroadcastSocketDevice from broadcast.h to mbroadcastsocketdevice.h
 * Moves MMulticastSocketDevice from multicast.{h,cpp} to mmulticastsocketdevice.{h,cpp}
   Also extends writeBlock method to multicast on all IPv4 addresses other than localhost;
   this ensures that devices that show up on their own internal networks (like an Ceton
   OCUR recorder) can see our broadcasts.
 * This also fixes numerous small bugs.
  • Loading branch information
daniel-kristjansson committed Jun 17, 2011
1 parent 39a787d commit 957f2ef
Show file tree
Hide file tree
Showing 28 changed files with 1,034 additions and 757 deletions.
45 changes: 8 additions & 37 deletions mythtv/libs/libmyth/backendselect.cpp
Expand Up @@ -247,41 +247,16 @@ void BackendSelection::Load()

void BackendSelection::Init(void)
{
EntryMap::Iterator it;
EntryMap ourMap;
DeviceLocation *pDevLoc;

SSDPCacheEntries *pEntries = SSDPCache::Instance()->Find( gBackendURI );

if (!pEntries)
{
VERBOSE(VB_GENERAL, "Found zero backends, bailing");
return;
}

pEntries->AddRef();
pEntries->Lock();

EntryMap *pMap = pEntries->GetEntryMap();

for (it = pMap->begin(); it != pMap->end(); ++it)
SSDPCacheEntries *pEntries = SSDPCache::Instance()->Find(gBackendURI);
if (pEntries)
{
pDevLoc = (DeviceLocation *)*it;

if (!pDevLoc)
continue;
EntryMap ourMap;
pEntries->GetEntryMap(ourMap);
pEntries->Release();

pDevLoc->AddRef();
ourMap.insert(pDevLoc->m_sUSN, pDevLoc);
}

pEntries->Unlock();
pEntries->Release();

for (it = ourMap.begin(); it != ourMap.end(); ++it)
{
pDevLoc = (DeviceLocation *)*it;
AddItem(pDevLoc); // this does a Release()
EntryMap::const_iterator it;
for (it = ourMap.begin(); it != ourMap.end(); ++it)
AddItem(*it); // this does an (*it)->Release()
}
}

Expand Down Expand Up @@ -341,12 +316,8 @@ void BackendSelection::customEvent(QEvent *event)
URI.startsWith("urn:schemas-mythtv-org:device:MasterMediaServer:"))
{
DeviceLocation *devLoc = SSDP::Instance()->Find(URI, URN);

if (devLoc)
{
devLoc->AddRef();
AddItem(devLoc); // this does a Release()
}
}
else if (message.startsWith("SSDP_REMOVE"))
{
Expand Down
19 changes: 9 additions & 10 deletions mythtv/libs/libmyth/mythcontext.cpp
Expand Up @@ -736,10 +736,7 @@ int MythContextPrivate::UPnPautoconf(const int milliSeconds)
{
backends = SSDP::Instance()->Find( gBackendURI );
if (backends)
{
backends->AddRef();
break;
}
putchar('.');
}
putchar('\n');
Expand Down Expand Up @@ -771,19 +768,17 @@ int MythContextPrivate::UPnPautoconf(const int milliSeconds)
return count;
}


// Get this backend's location:
backends->Lock();
DeviceLocation *BE = *(backends->GetEntryMap()->begin());
backends->Unlock();
DeviceLocation *BE = backends->GetFirst();
backends->Release();

// We don't actually know the backend's access PIN, so this will
// only work for ones that have PIN access disabled (i.e. 0000)
if (UPnPconnect(BE, QString::null))
return 1;
int ret = (UPnPconnect(BE, QString::null)) ? 1 : -1;

BE->Release();

return -1; // Try to force chooser & PIN
return ret;
}

/**
Expand Down Expand Up @@ -850,9 +845,13 @@ bool MythContextPrivate::DefaultUPnP(QString &error)
gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
}

pDevLoc->Release();

return true;
}

pDevLoc->Release();

error = "Cannot connect to default backend via UPnP. Wrong saved PIN?";
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions mythtv/libs/libmythbase/msocketdevice.h
Expand Up @@ -114,10 +114,10 @@ class MBASE_PUBLIC MSocketDevice: public QIODevice
inline qint64 readBlock(char *data, quint64 maxlen)
{ return qint64(read(data, qint64(maxlen))); }

quint16 port() const;
quint16 peerPort() const;
QHostAddress address() const;
QHostAddress peerAddress() const;
virtual quint16 port() const;
virtual quint16 peerPort() const;
virtual QHostAddress address() const;
virtual QHostAddress peerAddress() const;

enum Error {
NoError,
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythupnp/eventing.h
Expand Up @@ -28,7 +28,7 @@
#include <QUuid>
#include <QMap>

#include "upnpimpl.h"
#include "upnpserviceimpl.h"
#include "upnputil.h"
#include "httpserver.h"

Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythupnp/httpserver.cpp
Expand Up @@ -31,6 +31,9 @@
#include <sys/utsname.h>
#endif

// Qt headers
#include <QScriptEngine>

// MythTV headers
#include "httpserver.h"
#include "upnputil.h"
Expand Down
5 changes: 2 additions & 3 deletions mythtv/libs/libmythupnp/httpserver.h
Expand Up @@ -33,10 +33,8 @@
#endif

// Qt headers
#include <QThread>
#include <QTcpServer>
#include <QReadWriteLock>
#include <QScriptEngine>
#include <QTcpServer>
#include <QMultiMap>

// MythTV headers
Expand All @@ -49,6 +47,7 @@
typedef struct timeval TaskTime;

class HttpWorkerThread;
class QScriptEngine;
class HttpServer;

/////////////////////////////////////////////////////////////////////////////
Expand Down
10 changes: 7 additions & 3 deletions mythtv/libs/libmythupnp/libmythupnp.pro
Expand Up @@ -17,23 +17,27 @@ QMAKE_CLEAN += version.cpp

# Input

HEADERS += mmulticastsocketdevice.h mbroadcastsocketdevice.h
HEADERS += httprequest.h upnp.h ssdp.h taskqueue.h upnpsubscription.h
HEADERS += upnpdevice.h upnptasknotify.h upnptasksearch.h threadpool.h upnputil.h
HEADERS += httpserver.h upnpcds.h upnpcdsobjects.h bufferedsocketdevice.h upnpmsrr.h
HEADERS += eventing.h upnpcmgr.h upnptaskevent.h upnptaskcache.h ssdpcache.h
HEADERS += upnpimpl.h multicast.h broadcast.h configuration.h
HEADERS += configuration.h
HEADERS += soapclient.h mythxmlclient.h mmembuf.h upnpexp.h
HEADERS += upnpserviceimpl.h
HEADERS += servicehost.h wsdl.h htmlserver.h serverSideScripting.h

HEADERS += serializers/serializer.h serializers/xmlSerializer.h
HEADERS += serializers/jsonSerializer.h serializers/soapSerializer.h

SOURCES += mmulticastsocketdevice.cpp
SOURCES += httprequest.cpp upnp.cpp ssdp.cpp taskqueue.cpp upnputil.cpp
SOURCES += upnpdevice.cpp upnptasknotify.cpp upnptasksearch.cpp threadpool.cpp
SOURCES += httpserver.cpp upnpcds.cpp upnpcdsobjects.cpp bufferedsocketdevice.cpp
SOURCES += eventing.cpp upnpcmgr.cpp upnpmsrr.cpp upnptaskevent.cpp ssdpcache.cpp
SOURCES += configuration.cpp soapclient.cpp mythxmlclient.cpp mmembuf.cpp
SOURCES += multicast.cpp htmlserver.cpp serverSideScripting.cpp
SOURCES += upnpserviceimpl.cpp
SOURCES += htmlserver.cpp serverSideScripting.cpp
SOURCES += servicehost.cpp wsdl.cpp upnpsubscription.cpp

SOURCES += serializers/serializer.cpp serializers/xmlSerializer.cpp
Expand All @@ -59,7 +63,7 @@ inc.files = httprequest.h upnp.h ssdp.h taskqueue.h bufferedsocketdevice.h
inc.files += upnpdevice.h upnptasknotify.h upnptasksearch.h threadpool.h upnputil.h
inc.files += httpserver.h httpstatus.h upnpcds.h upnpcdsobjects.h
inc.files += eventing.h upnpcmgr.h upnptaskevent.h upnptaskcache.h ssdpcache.h
inc.files += upnpimpl.h multicast.h broadcast.h configuration.h
inc.files += upnpimpl.h configuration.h
inc.files += soapclient.h mythxmlclient.h mmembuf.h upnpsubscription.h
inc.files += servicehost.h wsdl.h htmlserver.h serverSideScripting.h

Expand Down
Expand Up @@ -21,55 +21,58 @@
//
//////////////////////////////////////////////////////////////////////////////

#ifndef __BROADCAST_H__
#define __BROADCAST_H__
#ifndef _MBROADCAST_SOCKET_DEVICE_H_
#define _MBROADCAST_SOCKET_DEVICE_H_

#include <QString>

#include "msocketdevice.h"
#include "mythverbose.h"

/////////////////////////////////////////////////////////////////////////////
// Broadcast Socket is used for XBox (original) since Multicast is not supported
/////////////////////////////////////////////////////////////////////////////

class QBroadcastSocket : public MSocketDevice
class MBroadcastSocketDevice : public MSocketDevice
{
public:
public:
MBroadcastSocketDevice(QString sAddress, quint16 nPort) :
MSocketDevice(MSocketDevice::Datagram),
m_address(sAddress), m_port(nPort)
{
m_address.setAddress( sAddress );
m_port = nPort;

QHostAddress m_address;
quint16 m_port;
struct ip_mreq m_imr;
QByteArray addr = sAddress.toLatin1();
setProtocol(IPv4);
setSocket(createNewSocket(), MSocketDevice::Datagram);

public:

QBroadcastSocket( QString sAddress, quint16 nPort )
: MSocketDevice( MSocketDevice::Datagram )
int one = 1;
if (setsockopt(socket(), SOL_SOCKET, SO_BROADCAST,
&one, sizeof(one)) < 0)
{
m_address.setAddress( sAddress );
m_port = nPort;

QByteArray addr = sAddress.toLatin1();
setProtocol(IPv4);
setSocket(createNewSocket(), MSocketDevice::Datagram);
VERBOSE(VB_IMPORTANT, "MBroadcastSocketDevice: setsockopt - "
"SO_BROADCAST Error" + ENO);
}

int one = 1;
setAddressReusable(true);

if ( setsockopt( socket(), SOL_SOCKET, SO_BROADCAST, &one, sizeof( one )) < 0)
{
VERBOSE(VB_IMPORTANT, QString( "QBroadcastSocket: setsockopt - SO_BROADCAST Error" ));
}
bind(m_address, m_port);
}

setAddressReusable( true );
virtual ~MBroadcastSocketDevice()
{
int zero = 0;
setsockopt(socket(), SOL_SOCKET, SO_BROADCAST, &zero, sizeof(zero));
}

bind( m_address, m_port );
}
virtual QHostAddress address() const { return m_address; }
virtual quint16 port() const { return m_port; }

virtual ~QBroadcastSocket()
{
int zero = 0;

setsockopt( socket(), SOL_SOCKET, SO_BROADCAST, &zero, sizeof( zero ));
}
private:
QHostAddress m_address;
quint16 m_port;
struct ip_mreq m_imr;
};

#endif
#endif // _MBROADCAST_SOCKET_DEVICE_H_

0 comments on commit 957f2ef

Please sign in to comment.