00001
00002
00003
00004
00005
00006
00007
00008
00010
00011
00012 #include <cstdlib>
00013
00014
00015 #include <unistd.h>
00016 #include <sys/time.h>
00017
00018
00019 #include <qstringlist.h>
00020 #include <qdeepcopy.h>
00021 #include <quuid.h>
00022 #include <qdom.h>
00023 #include <qfile.h>
00024
00025
00026 #include "upnp.h"
00027 #include "multicast.h"
00028 #include "broadcast.h"
00029 #include "compat.h"
00030
00033
00034
00035
00038
00040
00042
00043 UPnpNotifyTask::UPnpNotifyTask( int nServicePort )
00044 {
00045 m_nServicePort = nServicePort;
00046 m_eNTS = NTS_alive;
00047
00048 m_nMaxAge = UPnp::g_pConfig->GetValue( "UPnP/SSDP/MaxAge" , 3600 );
00049 }
00050
00052
00054
00055 UPnpNotifyTask::~UPnpNotifyTask()
00056 {
00057 }
00058
00060
00062
00063 void UPnpNotifyTask::SendNotifyMsg( QSocketDevice *pSocket,
00064 QString sNT,
00065 QString sUDN )
00066 {
00067 QString sUSN;
00068
00069 if ( sUDN.length() > 0)
00070 sUSN = sUDN + "::" + sNT;
00071 else
00072 sUSN = sNT;
00073
00074 QString sData = QString ( "Server: %1, UPnP/1.0, MythTv %2\r\n"
00075 "NTS: %3\r\n"
00076 "NT: %4\r\n"
00077 "USN: %5\r\n"
00078 "CACHE-CONTROL: max-age=%6\r\n"
00079 "Content-Length: 0\r\n\r\n" )
00080 .arg( HttpServer::g_sPlatform )
00081 .arg( MYTH_BINARY_VERSION )
00082 .arg( GetNTSString() )
00083 .arg( sNT )
00084 .arg( sUSN )
00085 .arg( m_nMaxAge );
00086
00087
00088
00089
00090
00091
00092 {
00093 QMutexLocker qml(&m_mutex);
00094
00095
00096
00097
00098
00099 QStringList addressList = QDeepCopy<QStringList>(UPnp::g_IPAddrList);
00100
00101 for ( QStringList::Iterator it = addressList.begin();
00102 it != addressList.end();
00103 ++it )
00104 {
00105 if (!*it)
00106 {
00107 VERBOSE(VB_GENERAL,
00108 "UPnpNotifyTask::SendNotifyMsg - NULL in m_addressList");
00109 continue;
00110 }
00111
00112 QString sHeader = QString( "NOTIFY * HTTP/1.1\r\n"
00113 "HOST: %1:%2\r\n"
00114 "LOCATION: http://%3:%4/getDeviceDesc\r\n" )
00115 .arg( SSDP_GROUP )
00116 .arg( SSDP_PORT )
00117 .arg( *it )
00118 .arg( m_nServicePort);
00119
00120 QString sPacket = sHeader + sData;
00121 QCString scPacket = sPacket.utf8();
00122
00123
00124
00125
00126
00127 pSocket->writeBlock( scPacket, scPacket.length(), pSocket->address(), pSocket->port() );
00128 usleep( rand() % 250000 );
00129 pSocket->writeBlock( scPacket, scPacket.length(), pSocket->address(), pSocket->port() );
00130 }
00131 }
00132
00133 }
00134
00136
00138
00139 void UPnpNotifyTask::Execute( TaskQueue *pQueue )
00140 {
00141
00142 QSocketDevice *pMulticast = new QMulticastSocket( SSDP_GROUP , SSDP_PORT );
00143
00144
00145
00146
00147
00148
00149 UPnpDevice &device = UPnp::g_UPnpDeviceDesc.m_rootDevice;
00150
00151 SendNotifyMsg( pMulticast, "upnp:rootdevice", device.GetUDN() );
00152
00153
00154
00155
00156
00157
00158 ProcessDevice( pMulticast, &device );
00159
00160
00161
00162
00163
00164
00165 delete pMulticast;
00166
00167
00168 pMulticast = NULL;
00169
00170
00171 m_mutex.lock();
00172
00173 if (m_eNTS == NTS_alive)
00174 pQueue->AddTask( (m_nMaxAge / 2) * 1000, (Task *)this );
00175
00176 m_mutex.unlock();
00177
00178 }
00179
00181
00183
00184 void UPnpNotifyTask::ProcessDevice( QSocketDevice *pSocket, UPnpDevice *pDevice )
00185 {
00186
00187
00188
00189
00190
00191
00192
00193 SendNotifyMsg( pSocket, pDevice->GetUDN(), "" );
00194 SendNotifyMsg( pSocket, pDevice->m_sDeviceType, pDevice->GetUDN() );
00195
00196
00197
00198
00199
00200 for ( UPnpService *pService = pDevice->m_listServices.first();
00201 pService != NULL;
00202 pService = pDevice->m_listServices.next() )
00203 {
00204 SendNotifyMsg( pSocket, pService->m_sServiceType, pDevice->GetUDN() );
00205 }
00206
00207
00208
00209
00210
00211 for ( UPnpDevice *pEmbeddedDevice = pDevice->m_listDevices.first();
00212 pEmbeddedDevice != NULL;
00213 pEmbeddedDevice = pDevice->m_listDevices.next() )
00214 {
00215 ProcessDevice( pSocket, pEmbeddedDevice );
00216 }
00217 }