00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00012
00013
00014 #include <sys/types.h>
00015 #include <sys/time.h>
00016 #include <cerrno>
00017
00018
00019 #include <QUuid>
00020
00021
00022 #include "upnputil.h"
00023 #include "upnp.h"
00024 #include "compat.h"
00025 #include "mythconfig.h"
00026 #include "mythlogging.h"
00027
00028
00029 #ifndef USING_MINGW
00030 #include <net/if.h>
00031 #include <sys/ioctl.h>
00032 #endif // USING_MINGW
00033 #if HAVE_GETIFADDRS
00034 #include <ifaddrs.h>
00035 #endif
00036
00037 #include "zlib.h"
00038
00040
00042
00043 QString LookupUDN( QString sDeviceType )
00044 {
00045 QStringList sList = sDeviceType.split(':', QString::SkipEmptyParts);
00046 QString sLoc = "LookupUDN(" + sDeviceType + ')';
00047
00048 if (sList.size() <= 2)
00049 {
00050 LOG(VB_GENERAL, LOG_ERR, sLoc + "- bad device type '" +
00051 sDeviceType + "', not enough tokens");
00052 return QString();
00053 }
00054
00055 sList.removeLast();
00056 QString sName = "UPnP/UDN/" + sList.last();
00057 QString sUDN = UPnp::GetConfiguration()->GetValue( sName, "" );
00058
00059 LOG(VB_UPNP, LOG_INFO, sLoc + " sName=" + sName + ", sUDN=" + sUDN);
00060
00061 if (sUDN.isEmpty())
00062 {
00063 sUDN = QUuid::createUuid().toString();
00064 sUDN.chop(2);
00065
00066 Configuration *pConfig = UPnp::GetConfiguration();
00067
00068 pConfig->SetValue( sName, sUDN );
00069 pConfig->Save();
00070 }
00071
00072 return( sUDN );
00073 }
00074
00076
00077 #if HAVE_GETIFADDRS
00078
00079 long GetIPAddressList(QStringList &sStrList)
00080 {
00081 QString LOC = "GetIPAddressList() - ";
00082
00083 struct ifaddrs *list, *ifa;
00084
00085
00086 sStrList.clear();
00087
00088 if (getifaddrs(&list) == -1)
00089 {
00090 LOG(VB_UPNP, LOG_ERR, LOC + "getifaddrs failed: " + ENO);
00091 return 0;
00092 }
00093
00094 for (ifa=list; ifa; ifa=ifa->ifa_next)
00095 {
00096 if (!ifa->ifa_addr)
00097 continue;
00098 if (ifa->ifa_addr->sa_family != AF_INET)
00099 continue;
00100 if (ifa->ifa_flags & IFF_LOOPBACK)
00101 continue;
00102 if (!(ifa->ifa_flags & IFF_UP))
00103 continue;
00104
00105
00106 char address[16];
00107
00108 if (inet_ntop(ifa->ifa_addr->sa_family,
00109 &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
00110 address, sizeof(address)) == NULL)
00111 {
00112 LOG(VB_UPNP, LOG_ERR, LOC + "inet_ntop failed: " + ENO);
00113 continue;
00114 }
00115
00116 sStrList.append(address);
00117 LOG(VB_UPNP, LOG_DEBUG, LOC + QString("Added %1 as %2")
00118 .arg(ifa->ifa_name).arg(address));
00119 }
00120
00121 freeifaddrs(list);
00122
00123 return(sStrList.count());
00124 }
00125
00126 #else // HAVE_GETIFADDRS
00127
00128
00129
00130
00131 long GetIPAddressList( QStringList &sStrList )
00132 {
00133 #ifdef USING_MINGW
00134 LOG(VB_UPNP, LOG_NOTICE, "GetIPAddressList() not implemented in MinGW");
00135 return 0;
00136 #else
00137 sStrList.clear();
00138
00139 MSocketDevice socket( MSocketDevice::Datagram );
00140
00141 struct ifreq ifReqs[ 16 ];
00142 struct ifreq ifReq;
00143 struct ifconf ifConf;
00144
00145
00146
00147
00148
00149 ifConf.ifc_len = sizeof( struct ifreq ) * sizeof( ifReqs );
00150 ifConf.ifc_ifcu.ifcu_req = ifReqs;
00151
00152 if ( ioctl( socket.socket(), SIOCGIFCONF, &ifConf ) < 0)
00153 return( 0 );
00154
00155 long nCount = ifConf.ifc_len / sizeof( struct ifreq );
00156
00157
00158
00159
00160
00161 for (long nIdx = 0; nIdx < nCount; nIdx++ )
00162 {
00163
00164
00165
00166
00167 strcpy ( ifReq.ifr_name, ifReqs[ nIdx ].ifr_name );
00168
00169 if (ioctl ( socket.socket(), SIOCGIFFLAGS, &ifReq ) < 0)
00170 continue;
00171
00172
00173
00174
00175
00176 if ((ifReq.ifr_flags & IFF_LOOPBACK) || (!(ifReq.ifr_flags & IFF_UP)))
00177 continue;
00178
00179 if ( ifReqs[ nIdx ].ifr_addr.sa_family == AF_INET)
00180 {
00181 struct sockaddr_in addr;
00182
00183
00184
00185
00186
00187 memcpy (&addr, &(ifReqs[ nIdx ].ifr_addr), sizeof( ifReqs[ nIdx ].ifr_addr ));
00188
00189 if (addr.sin_addr.s_addr != htonl( INADDR_LOOPBACK ))
00190 {
00191 QHostAddress address( htonl( addr.sin_addr.s_addr ));
00192
00193 sStrList.append( address.toString() );
00194 }
00195 }
00196 }
00197
00198 return( sStrList.count() );
00199 #endif // !USING_MINGW
00200 }
00201
00202 #endif // HAVE_GETIFADDRS
00203
00205
00207
00208 bool operator< ( TaskTime t1, TaskTime t2 )
00209 {
00210 if ( (t1.tv_sec < t2.tv_sec) ||
00211 ((t1.tv_sec == t2.tv_sec) && (t1.tv_usec < t2.tv_usec)))
00212 {
00213 return true;
00214 }
00215
00216 return false;
00217 }
00218
00220
00222
00223 bool operator== ( TaskTime t1, TaskTime t2 )
00224 {
00225 if ((t1.tv_sec == t2.tv_sec) && (t1.tv_usec == t2.tv_usec))
00226 return true;
00227
00228 return false;
00229 }
00230
00232
00234
00235 void AddMicroSecToTaskTime( TaskTime &t, suseconds_t uSecs )
00236 {
00237 uSecs += t.tv_usec;
00238
00239 t.tv_sec += (uSecs / 1000000);
00240 t.tv_usec = (uSecs % 1000000);
00241 }
00242
00244
00246
00247 void AddSecondsToTaskTime( TaskTime &t, long nSecs )
00248 {
00249 t.tv_sec += nSecs;
00250 }
00251
00253
00255
00256 QByteArray gzipCompress( const QByteArray &data )
00257 {
00258 if (data.length() == 0)
00259 return QByteArray();
00260
00261 static const int CHUNK_SIZE = 1024;
00262 char out[ CHUNK_SIZE ];
00263
00264
00265 z_stream strm;
00266
00267 strm.zalloc = Z_NULL;
00268 strm.zfree = Z_NULL;
00269 strm.opaque = Z_NULL;
00270 strm.avail_in = data.length();
00271 strm.next_in = (Bytef*)(data.data());
00272
00273 int ret = deflateInit2( &strm,
00274 Z_DEFAULT_COMPRESSION,
00275 Z_DEFLATED,
00276 15 + 16,
00277 8,
00278 Z_DEFAULT_STRATEGY );
00279 if (ret != Z_OK)
00280 return QByteArray();
00281
00282 QByteArray result;
00283
00284
00285 do
00286 {
00287 strm.avail_out = CHUNK_SIZE;
00288 strm.next_out = (Bytef*)(out);
00289
00290 ret = deflate(&strm, Z_FINISH);
00291
00292 Q_ASSERT(ret != Z_STREAM_ERROR);
00293
00294 switch (ret)
00295 {
00296 case Z_NEED_DICT:
00297 ret = Z_DATA_ERROR;
00298 case Z_DATA_ERROR:
00299 case Z_MEM_ERROR:
00300 (void)deflateEnd(&strm);
00301 return QByteArray();
00302 }
00303
00304 result.append( out, CHUNK_SIZE - strm.avail_out );
00305 }
00306 while (strm.avail_out == 0);
00307
00308
00309
00310 deflateEnd(&strm);
00311
00312 return result;
00313 }