00001
00002
00003
00004
00005 #include <stdlib.h>
00006 #include <stdio.h>
00007 #include <zlib.h>
00008
00009 #include "dsmccobjcarousel.h"
00010 #include "dsmccreceiver.h"
00011 #include "dsmcccache.h"
00012 #include "dsmcc.h"
00013
00014 #include "mythlogging.h"
00015
00016
00017 DSMCCCacheModuleData::DSMCCCacheModuleData(DsmccDii *dii,
00018 DsmccModuleInfo *info,
00019 unsigned short streamTag)
00020 : m_carousel_id(dii->download_id), m_module_id(info->module_id),
00021 m_stream_id(streamTag), m_version(info->module_version),
00022 m_moduleSize(info->module_size), m_receivedData(0),
00023 m_completed(false)
00024 {
00025
00026 int num_blocks = (m_moduleSize + dii->block_size - 1) / dii->block_size;
00027 m_blocks.resize(num_blocks, NULL);
00028
00029
00030 m_descriptorData = info->modinfo.descriptorData;
00031 }
00032
00033 DSMCCCacheModuleData::~DSMCCCacheModuleData()
00034 {
00035 vector<QByteArray*>::iterator it = m_blocks.begin();
00036 for (; it != m_blocks.end(); ++it)
00037 delete *it;
00038 m_blocks.clear();
00039 }
00040
00045 unsigned char *DSMCCCacheModuleData::AddModuleData(DsmccDb *ddb,
00046 const unsigned char *data)
00047 {
00048 if (m_version != ddb->module_version)
00049 {
00050 LOG(VB_DSMCC, LOG_WARNING, QString("[dsmcc] Module %1 my version %2 != %3")
00051 .arg(ddb->module_id).arg(m_version).arg(ddb->module_version));
00052 return NULL;
00053 }
00054
00055 if (m_completed)
00056 return NULL;
00057
00058 if (ddb->block_number >= m_blocks.size())
00059 {
00060 LOG(VB_DSMCC, LOG_WARNING, QString("[dsmcc] Module %1 block number %2 "
00061 "is larger than %3")
00062 .arg(ddb->module_id).arg(ddb->block_number)
00063 .arg(m_blocks.size()));
00064 return NULL;
00065 }
00066
00067
00068 if (m_blocks[ddb->block_number])
00069 {
00070 QString s;
00071 for (unsigned i = 0; i < m_blocks.size(); ++i)
00072 s += m_blocks[i] ? '+' : 'X';
00073
00074 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] Module %1 block %2 dup: %3")
00075 .arg(ddb->module_id).arg(ddb->block_number +1).arg(s));
00076
00077 return NULL;
00078 }
00079
00080
00081 m_blocks[ddb->block_number] = new QByteArray((char*) data, ddb->len);
00082 if (m_blocks[ddb->block_number])
00083 m_receivedData += ddb->len;
00084
00085 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] Module %1 block %2/%3 bytes %4/%5")
00086 .arg(ddb->module_id)
00087 .arg(ddb->block_number +1).arg(m_blocks.size())
00088 .arg(m_receivedData).arg(m_moduleSize));
00089
00090 if (m_receivedData < m_moduleSize)
00091 return NULL;
00092
00093 LOG(VB_DSMCC, LOG_INFO,
00094 QString("[dsmcc] Reconstructing module %1 from blocks")
00095 .arg(m_module_id));
00096
00097
00098 unsigned char *tmp_data = (unsigned char*) malloc(m_receivedData);
00099 if (tmp_data == NULL)
00100 return NULL;
00101
00102 uint curp = 0;
00103 for (uint i = 0; i < m_blocks.size(); i++)
00104 {
00105 QByteArray *block = m_blocks[i];
00106 m_blocks[i] = NULL;
00107 uint size = block->size();
00108 memcpy(tmp_data + curp, block->data(), size);
00109 curp += size;
00110 delete block;
00111 }
00112
00113
00114 if (m_descriptorData.isCompressed)
00115 {
00116 unsigned long dataLen = m_descriptorData.originalSize;
00117 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] uncompressing: "
00118 "compressed size %1, final size %2")
00119 .arg(m_moduleSize).arg(dataLen));
00120
00121 unsigned char *uncompressed = (unsigned char*) malloc(dataLen);
00122 int ret = uncompress(uncompressed, &dataLen, tmp_data, m_moduleSize);
00123 if (ret != Z_OK)
00124 {
00125 LOG(VB_DSMCC, LOG_ERR, "[dsmcc] compression error, skipping");
00126 free(tmp_data);
00127 free(uncompressed);
00128 return NULL;
00129 }
00130
00131 free(tmp_data);
00132 tmp_data = uncompressed;
00133 }
00134
00135 m_completed = true;
00136 m_blocks.clear();
00137 return tmp_data;
00138 }
00139
00140
00141 ObjCarousel::ObjCarousel(Dsmcc *dsmcc)
00142 : filecache(dsmcc), m_id(0)
00143 {
00144 }
00145
00146 ObjCarousel::~ObjCarousel()
00147 {
00148 QLinkedList<DSMCCCacheModuleData*>::iterator it = m_Cache.begin();
00149 for (; it != m_Cache.end(); ++it)
00150 delete *it;
00151 m_Cache.clear();
00152 }
00153
00154 void ObjCarousel::AddModuleInfo(DsmccDii *dii, Dsmcc *status,
00155 unsigned short streamTag)
00156 {
00157 for (int i = 0; i < dii->number_modules; i++)
00158 {
00159 DsmccModuleInfo *info = &(dii->modules[i]);
00160 bool bFound = false;
00161
00162
00163
00164 QLinkedList<DSMCCCacheModuleData*>::iterator it = m_Cache.begin();
00165 for ( ; it != m_Cache.end(); ++it)
00166 {
00167 DSMCCCacheModuleData *cachep = *it;
00168 if (cachep->CarouselId() == dii->download_id &&
00169 cachep->ModuleId() == info->module_id)
00170 {
00171
00172 if (cachep->Version() == info->module_version)
00173 {
00174 LOG(VB_DSMCC, LOG_DEBUG, QString("[dsmcc] Already Know Module %1")
00175 .arg(info->module_id));
00176
00177 if (cachep->ModuleSize() == info->module_size)
00178 {
00179 bFound = true;
00180 break;
00181 }
00182
00183
00184
00185 LOG(VB_DSMCC, LOG_ERR,
00186 QString("[dsmcc] Module %1 size has changed (%2 to %3) "
00187 "but version has not!!")
00188 .arg(info->module_id)
00189 .arg(info->module_size)
00190 .arg(cachep->DataSize()));
00191 }
00192
00193 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] Updated Module %1")
00194 .arg(info->module_id));
00195
00196
00197 m_Cache.erase(it);
00198 delete cachep;
00199 break;
00200 }
00201 }
00202
00203 if (bFound)
00204 continue;
00205
00206 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] Saving info for module %1")
00207 .arg(dii->modules[i].module_id));
00208
00209
00210 DSMCCCacheModuleData *cachep = new DSMCCCacheModuleData(dii, info, streamTag);
00211 int tag = info->modinfo.tap.assoc_tag;
00212 LOG(VB_DSMCC, LOG_DEBUG, QString("[dsmcc] Module info tap identifies "
00213 "tag %1 with carousel %2")
00214 .arg(tag).arg(cachep->CarouselId()));
00215
00216
00217 status->AddTap(tag, cachep->CarouselId());
00218
00219
00220 m_Cache.append(cachep);
00221 }
00222 }
00223
00229 void ObjCarousel::AddModuleData(DsmccDb *ddb, const unsigned char *data)
00230 {
00231 LOG(VB_DSMCC, LOG_DEBUG, QString("[dsmcc] Data block on carousel %1").arg(m_id));
00232
00233
00234 QLinkedList<DSMCCCacheModuleData*>::iterator it = m_Cache.begin();
00235 for (; it != m_Cache.end(); ++it)
00236 {
00237 DSMCCCacheModuleData *cachep = *it;
00238 if (cachep->CarouselId() == m_id &&
00239 (cachep->ModuleId() == ddb->module_id))
00240 {
00241
00242 unsigned char *tmp_data = cachep->AddModuleData(ddb, data);
00243 if (tmp_data)
00244 {
00245
00246 unsigned int len = cachep->DataSize();
00247 unsigned long curp = 0;
00248 LOG(VB_DSMCC, LOG_DEBUG, QString("[biop] Module size (uncompressed) = %1").arg(len));
00249
00250
00251
00252
00253 while (curp < len)
00254 {
00255 BiopMessage bm;
00256 if (!bm.Process(cachep, &filecache, tmp_data, &curp))
00257 break;
00258 }
00259 free(tmp_data);
00260 }
00261 return;
00262 }
00263 }
00264 LOG(VB_DSMCC, LOG_INFO, QString("[dsmcc] Data block module %1 not on carousel %2")
00265 .arg(ddb->module_id).arg(m_id));
00266 }