00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013
00014 #include <cstdlib>
00015
00016
00017 #include <QStringList>
00018 #include <QUuid>
00019 #include <QFile>
00020
00021
00022 #include "mmulticastsocketdevice.h"
00023 #include "mythlogging.h"
00024 #include "mythversion.h"
00025 #include "compat.h"
00026 #include "upnp.h"
00027
00030
00031
00032
00035
00037
00039
00040 UPnpNotifyTask::UPnpNotifyTask( int nServicePort )
00041 {
00042 m_nServicePort = nServicePort;
00043 m_eNTS = NTS_alive;
00044
00045 m_nMaxAge = UPnp::GetConfiguration()->GetValue( "UPnP/SSDP/MaxAge" , 3600 );
00046 }
00047
00049
00051
00052 UPnpNotifyTask::~UPnpNotifyTask()
00053 {
00054 }
00055
00057
00059
00060 void UPnpNotifyTask::SendNotifyMsg( MSocketDevice *pSocket,
00061 QString sNT,
00062 QString sUDN )
00063 {
00064 QString sUSN;
00065
00066 if ( sUDN.length() > 0)
00067 sUSN = sUDN + "::" + sNT;
00068 else
00069 sUSN = sNT;
00070
00071 QString sData = QString ( "Server: %1, UPnP/1.0, MythTV %2\r\n"
00072 "NTS: %3\r\n"
00073 "NT: %4\r\n"
00074 "USN: %5\r\n"
00075 "CACHE-CONTROL: max-age=%6\r\n"
00076 "Content-Length: 0\r\n\r\n" )
00077 .arg( HttpServer::GetPlatform() )
00078 .arg( MYTH_BINARY_VERSION )
00079 .arg( GetNTSString() )
00080 .arg( sNT )
00081 .arg( sUSN )
00082 .arg( m_nMaxAge );
00083
00084 LOG(VB_UPNP, LOG_INFO,
00085 QString("UPnpNotifyTask::SendNotifyMsg : %1:%2 : %3 : %4")
00086 .arg(pSocket->address().toString()) .arg(pSocket->port())
00087 .arg(sNT) .arg(sUSN));
00088
00089 QMutexLocker qml(&m_mutex);
00090
00091
00092
00093
00094
00095 QStringList addressList = UPnp::g_IPAddrList;
00096
00097 for ( QStringList::Iterator it = addressList.begin();
00098 it != addressList.end();
00099 ++it )
00100 {
00101 if ((*it).isEmpty())
00102 {
00103 LOG(VB_GENERAL, LOG_ERR,
00104 "UPnpNotifyTask::SendNotifyMsg - NULL in address list");
00105 continue;
00106 }
00107
00108 QString ipaddress = *it;
00109
00110
00111 if (ipaddress.contains(":"))
00112 ipaddress = "[" + ipaddress + "]";
00113
00114 QString sHeader = QString("NOTIFY * HTTP/1.1\r\n"
00115 "HOST: %1:%2\r\n"
00116 "LOCATION: http://%3:%4/getDeviceDesc\r\n")
00117 .arg(pSocket->address().toString()) .arg(pSocket->port())
00118 .arg(ipaddress) .arg(m_nServicePort);
00119
00120 QString sPacket = sHeader + sData;
00121 QByteArray scPacket = sPacket.toUtf8();
00122
00123
00124
00125
00126
00127 pSocket->writeBlock( scPacket, scPacket.length(),
00128 pSocket->address(), pSocket->port() );
00129 usleep( random() % 250000 );
00130 pSocket->writeBlock( scPacket, scPacket.length(),
00131 pSocket->address(), pSocket->port() );
00132 }
00133 }
00134
00136
00138
00139 void UPnpNotifyTask::Execute( TaskQueue *pQueue )
00140 {
00141 MSocketDevice *pMulticast = new MMulticastSocketDevice(
00142 SSDP_GROUP, SSDP_PORT);
00143
00144
00145
00146
00147
00148 UPnpDevice &device = UPnp::g_UPnpDeviceDesc.m_rootDevice;
00149
00150 SendNotifyMsg( pMulticast, "upnp:rootdevice", device.GetUDN() );
00151
00152
00153
00154
00155
00156 ProcessDevice( pMulticast, &device );
00157
00158
00159
00160
00161
00162 delete pMulticast;
00163
00164 pMulticast = NULL;
00165
00166 m_mutex.lock();
00167
00168 if (m_eNTS == NTS_alive)
00169 pQueue->AddTask( (m_nMaxAge / 2) * 1000, (Task *)this );
00170
00171 m_mutex.unlock();
00172
00173 }
00174
00176
00178
00179 void UPnpNotifyTask::ProcessDevice(
00180 MSocketDevice *pSocket, UPnpDevice *pDevice)
00181 {
00182
00183
00184
00185
00186
00187
00188
00189 SendNotifyMsg( pSocket, pDevice->GetUDN(), "" );
00190 SendNotifyMsg( pSocket, pDevice->m_sDeviceType, pDevice->GetUDN() );
00191
00192
00193
00194
00195
00196 UPnpServiceList::const_iterator sit = pDevice->m_listServices.begin();
00197 for (; sit != pDevice->m_listServices.end(); ++sit)
00198 SendNotifyMsg( pSocket, (*sit)->m_sServiceType, pDevice->GetUDN() );
00199
00200
00201
00202
00203
00204 UPnpDeviceList::iterator dit = pDevice->m_listDevices.begin();
00205 for (; dit != pDevice->m_listDevices.end(); ++dit)
00206 ProcessDevice( pSocket, *dit);
00207 }