|
MythTV
0.26-pre
|
00001 00002 // Program Name: upnptasksearch.cpp 00003 // Created : Oct. 24, 2005 00004 // 00005 // Purpose : UPnp Task to handle Discovery Responses 00006 // 00007 // Copyright (c) 2005 David Blain <dblain@mythtv.org> 00008 // 00009 // Licensed under the GPL v2 or later, see COPYING for details 00010 // 00012 00013 #include <compat.h> 00014 #include <stdlib.h> 00015 00016 #include <QStringList> 00017 #include <QFile> 00018 #include <QDateTime> 00019 00020 #include "upnp.h" 00021 #include "upnptasksearch.h" 00022 #include "mythversion.h" 00023 #include "compat.h" 00024 00027 // 00028 // UPnpSearchTask Implementation 00029 // 00032 00034 // 00036 00037 UPnpSearchTask::UPnpSearchTask( int nServicePort, 00038 QHostAddress peerAddress, 00039 int nPeerPort, 00040 QString sST, 00041 QString sUDN ) 00042 { 00043 m_PeerAddress = peerAddress; 00044 m_nPeerPort = nPeerPort; 00045 m_sST = sST; 00046 m_sUDN = sUDN; 00047 m_nServicePort= nServicePort; 00048 m_nMaxAge = UPnp::GetConfiguration()->GetValue( "UPnP/SSDP/MaxAge" , 3600 ); 00049 00050 } 00051 00053 // 00055 00056 UPnpSearchTask::~UPnpSearchTask() 00057 { 00058 } 00059 00061 // 00063 00064 void UPnpSearchTask::SendMsg( MSocketDevice *pSocket, 00065 QString sST, 00066 QString sUDN ) 00067 { 00068 QString sUSN; 00069 00070 if (( sUDN.length() > 0) && ( sUDN != sST )) 00071 sUSN = sUDN + "::" + sST; 00072 else 00073 sUSN = sST; 00074 00075 QString sDate = QDateTime::currentDateTime().toString( "d MMM yyyy hh:mm:ss" ); 00076 00077 QString sData = QString ( "CACHE-CONTROL: max-age=%1\r\n" 00078 "DATE: %2\r\n" 00079 "EXT:\r\n" 00080 "Server: %3, UPnP/1.0, MythTV %4\r\n" 00081 "ST: %5\r\n" 00082 "USN: %6\r\n" 00083 "Content-Length: 0\r\n\r\n" ) 00084 .arg( m_nMaxAge ) 00085 .arg( sDate ) 00086 .arg( HttpServer::GetPlatform() ) 00087 .arg( MYTH_BINARY_VERSION ) 00088 .arg( sST ) 00089 .arg( sUSN ); 00090 00091 #if 0 00092 LOG(VB_UPNP, LOG_DEBUG, QString("UPnpSearchTask::SendMsg : %1 : %2 ") 00093 .arg(sST) .arg(sUSN)); 00094 00095 LOG(VB_UPNP, LOG_DEBUG, 00096 QString("UPnpSearchTask::SendMsg m_PeerAddress = %1 Port=%2") 00097 .arg(m_PeerAddress.toString()) .arg(m_nPeerPort)); 00098 #endif 00099 00100 for ( QStringList::Iterator it = m_addressList.begin(); 00101 it != m_addressList.end(); 00102 ++it ) 00103 { 00104 QString ipaddress = *it; 00105 00106 // If this looks like an IPv6 address, then enclose it in []'s 00107 if (ipaddress.contains(":")) 00108 ipaddress = "[" + ipaddress + "]"; 00109 00110 QString sHeader = QString ( "HTTP/1.1 200 OK\r\n" 00111 "LOCATION: http://%1:%2/getDeviceDesc\r\n" ) 00112 .arg( ipaddress ) 00113 .arg( m_nServicePort); 00114 00115 00116 QString sPacket = sHeader + sData; 00117 QByteArray scPacket = sPacket.toUtf8(); 00118 00119 // ------------------------------------------------------------------ 00120 // Send Packet to UDP Socket (Send same packet twice) 00121 // ------------------------------------------------------------------ 00122 00123 pSocket->writeBlock( scPacket, scPacket.length(), m_PeerAddress, 00124 m_nPeerPort ); 00125 usleep( random() % 250000 ); 00126 pSocket->writeBlock( scPacket, scPacket.length(), m_PeerAddress, 00127 m_nPeerPort ); 00128 } 00129 } 00130 00132 // 00134 00135 void UPnpSearchTask::Execute( TaskQueue * /*pQueue*/ ) 00136 { 00137 MSocketDevice *pSocket = new MSocketDevice( MSocketDevice::Datagram ); 00138 00139 // ---------------------------------------------------------------------- 00140 // Refresh IP Address List in case of changes 00141 // ---------------------------------------------------------------------- 00142 00143 m_addressList = UPnp::g_IPAddrList; 00144 00145 // ---------------------------------------------------------------------- 00146 // Check to see if this is a rootdevice or all request. 00147 // ---------------------------------------------------------------------- 00148 00149 UPnpDevice &device = UPnp::g_UPnpDeviceDesc.m_rootDevice; 00150 00151 if ((m_sST == "upnp:rootdevice") || (m_sST == "ssdp:all" )) 00152 { 00153 SendMsg( pSocket, "upnp:rootdevice", device.GetUDN() ); 00154 00155 if (m_sST == "ssdp:all") 00156 ProcessDevice( pSocket, &device ); 00157 } 00158 else 00159 { 00160 // ------------------------------------------------------------------ 00161 // Send Device/Service specific response. 00162 // ------------------------------------------------------------------ 00163 00164 SendMsg( pSocket, m_sST, m_sUDN ); 00165 } 00166 00167 delete pSocket; 00168 pSocket = NULL; 00169 } 00170 00172 // 00174 00175 void UPnpSearchTask::ProcessDevice( 00176 MSocketDevice *pSocket, UPnpDevice *pDevice) 00177 { 00178 // ---------------------------------------------------------------------- 00179 // Loop for each device and send the 2 required messages 00180 // 00181 // -=>TODO: We need to add support to only notify 00182 // Version 1 of a service. 00183 // ---------------------------------------------------------------------- 00184 00185 SendMsg( pSocket, pDevice->GetUDN(), "" ); 00186 SendMsg( pSocket, pDevice->m_sDeviceType, pDevice->GetUDN() ); 00187 00188 // ------------------------------------------------------------------ 00189 // Loop for each service in this device and send the 1 required message 00190 // ------------------------------------------------------------------ 00191 00192 UPnpServiceList::const_iterator sit = pDevice->m_listServices.begin(); 00193 for (; sit != pDevice->m_listServices.end(); ++sit) 00194 SendMsg(pSocket, (*sit)->m_sServiceType, pDevice->GetUDN()); 00195 00196 // ---------------------------------------------------------------------- 00197 // Process any Embedded Devices 00198 // ---------------------------------------------------------------------- 00199 00200 UPnpDeviceList::const_iterator dit = pDevice->m_listDevices.begin(); 00201 for (; dit != pDevice->m_listDevices.end(); ++dit) 00202 ProcessDevice( pSocket, *dit); 00203 } 00204
1.7.6.1