00001
00002
00003
00004
00005
00006 #include <stdlib.h>
00007 #include <string.h>
00008
00009 #include "dsmccbiop.h"
00010 #include "dsmccreceiver.h"
00011 #include "dsmcccache.h"
00012 #include "dsmccobjcarousel.h"
00013 #include "dsmcc.h"
00014
00015 #include "mythlogging.h"
00016
00017 BiopNameComp::~BiopNameComp()
00018 {
00019 if (m_id)
00020 free(m_id);
00021 if (m_kind)
00022 free(m_kind);
00023 }
00024
00025 int BiopNameComp::Process(const unsigned char *data)
00026 {
00027 int off = 0;
00028
00029 m_id_len = data[off++];
00030 m_id = (char*) malloc(m_id_len);
00031 memcpy(m_id, data + off, m_id_len);
00032
00033 off += m_id_len;
00034 m_kind_len = data[off++];
00035 m_kind = (char*) malloc(m_kind_len);
00036 memcpy(m_kind, data + off, m_kind_len);
00037
00038 off += m_kind_len;
00039
00040 return off;
00041 }
00042
00043 BiopName::BiopName()
00044 {
00045 m_comp_count = 0;
00046 m_comps = NULL;
00047 }
00048
00049 BiopName::~BiopName()
00050 {
00051 delete[] m_comps;
00052 }
00053
00054 int BiopName::Process(const unsigned char *data)
00055 {
00056 int off = 0;
00057 m_comp_count = data[0];
00058
00059 if (m_comp_count != 1)
00060 LOG(VB_DSMCC, LOG_WARNING, "[biop] Expected one name");
00061
00062 off++;
00063 m_comps = new BiopNameComp[m_comp_count];
00064
00065 for (int i = 0; i < m_comp_count; i++)
00066 {
00067 int ret = m_comps[i].Process(data + off);
00068 if (ret <= 0)
00069 return ret;
00070 off += ret;
00071 }
00072
00073 return off;
00074 }
00075
00076 int BiopBinding::Process(const unsigned char *data)
00077 {
00078 int off = 0, ret;
00079 ret = m_name.Process(data);
00080
00081 if (ret > 0)
00082 off += ret;
00083 else
00084 return ret;
00085
00086 m_binding_type = data[off++];
00087 ret = m_ior.Process(data + off);
00088
00089 if (ret > 0)
00090 off += ret;
00091 else
00092 return ret;
00093
00094 m_objinfo_len = (data[off] << 8) | data[off + 1];
00095 off += 2;
00096
00097 if (m_objinfo_len > 0)
00098 {
00099 m_objinfo = (char*) malloc(m_objinfo_len);
00100 memcpy(m_objinfo, data + off, m_objinfo_len);
00101 }
00102 else
00103 m_objinfo = NULL;
00104
00105 off += m_objinfo_len;
00106
00107 return off;
00108 }
00109
00110 BiopBinding::~BiopBinding()
00111 {
00112 free(m_objinfo);
00113 }
00114
00115 bool BiopMessage::Process(DSMCCCacheModuleData *cachep, DSMCCCache *filecache,
00116 unsigned char *data, unsigned long *curp)
00117 {
00118
00119 if (! ProcessMsgHdr(data, curp))
00120 {
00121 LOG(VB_DSMCC, LOG_ERR,
00122 "[biop] Invalid biop header, dropping rest of module");
00123
00124
00125 return false;
00126 }
00127
00128
00129 if (strcmp(m_objkind, "fil") == 0)
00130 {
00131 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing file");
00132 return ProcessFile(cachep, filecache, data, curp);
00133 }
00134 else if (strcmp(m_objkind, "dir") == 0)
00135 {
00136 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing directory");
00137 return ProcessDir(false, cachep, filecache, data, curp);
00138 }
00139 else if (strcmp(m_objkind, "srg") == 0)
00140 {
00141 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing gateway");
00142 return ProcessDir(true, cachep, filecache, data, curp);
00143 }
00144 else
00145 {
00146
00147 LOG(VB_DSMCC, LOG_WARNING, QString("Unknown or unsupported format %1%2%3%4")
00148 .arg(m_objkind[0]).arg(m_objkind[1])
00149 .arg(m_objkind[2]).arg(m_objkind[3]));
00150 return false;
00151 }
00152 }
00153
00154 BiopMessage::~BiopMessage()
00155 {
00156 free(m_objinfo);
00157 free(m_objkind);
00158 }
00159
00160 bool BiopMessage::ProcessMsgHdr(unsigned char *data, unsigned long *curp)
00161 {
00162 const unsigned char *buf = data + (*curp);
00163 int off = 0;
00164
00165 if (buf[off] !='B' || buf[off +1] !='I' || buf[off +2] !='O' || buf[off +3] !='P')
00166 {
00167 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage - invalid header");
00168 return false;
00169 }
00170 off += 4;
00171
00172 m_version_major = buf[off++];
00173 m_version_minor = buf[off++];
00174 if (m_version_major != 1 || m_version_minor != 0)
00175 {
00176 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid version");
00177 return false;
00178 }
00179
00180 if (buf[off++] != 0)
00181 {
00182 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid byte order");
00183 return false;
00184 }
00185 if (buf[off++] != 0)
00186 {
00187 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid message type");
00188 return false;
00189 }
00190
00191 m_message_size = ((buf[off + 0] << 24) | (buf[off+1] << 16) |
00192 (buf[off + 2] << 8) | (buf[off + 3]));
00193 off += 4;
00194
00195 uint nObjLen = buf[off++];
00196 m_objkey = DSMCCCacheKey((const char*)buf + off, nObjLen);
00197 off += nObjLen;
00198
00199 m_objkind_len = ((buf[off + 0] << 24) | (buf[off + 1] << 16) |
00200 (buf[off + 2] << 8) | (buf[off + 3]));
00201 off += 4;
00202 m_objkind = (char*) malloc(m_objkind_len);
00203 memcpy(m_objkind, buf + off, m_objkind_len);
00204 off += m_objkind_len;
00205
00206 m_objinfo_len = buf[off] << 8 | buf[off + 1];
00207 off += 2;
00208 m_objinfo = (char*) malloc(m_objinfo_len);
00209 memcpy(m_objinfo, buf + off, m_objinfo_len);
00210 off += m_objinfo_len;
00211
00212 (*curp) += off;
00213
00214 return true;
00215 }
00216
00217
00226 bool BiopMessage::ProcessDir(
00227 bool isSrg, DSMCCCacheModuleData *cachep, DSMCCCache *filecache,
00228 unsigned char *data, unsigned long *curp)
00229 {
00230 int off = 0;
00231 const unsigned char * const buf = data + (*curp);
00232
00233 if (m_objinfo_len)
00234 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir non-zero objectInfo_length");
00235
00236 const unsigned serviceContextList_count = buf[off++];
00237 if (serviceContextList_count)
00238 {
00239
00240 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessDir serviceContextList count %1")
00241 .arg(serviceContextList_count));
00242 return false;
00243 }
00244
00245 unsigned long msgbody_len = ((buf[off + 0] << 24) | (buf[off + 1] << 16) |
00246 (buf[off + 2] << 8) | (buf[off + 3]));
00247 off += 4;
00248 int const start = off;
00249
00250 unsigned int bindings_count = buf[off] << 8 | buf[off + 1];
00251 off += 2;
00252
00253 DSMCCCacheReference ref(cachep->CarouselId(), cachep->ModuleId(),
00254 cachep->StreamId(), m_objkey);
00255 DSMCCCacheDir *pDir = isSrg ? filecache->Srg(ref) : filecache->Directory(ref);
00256
00257 for (uint i = 0; i < bindings_count; i++)
00258 {
00259 BiopBinding binding;
00260 int ret = binding.Process(buf + off);
00261 if (ret > 0)
00262 off += ret;
00263 else
00264 return false;
00265
00266 if (binding.m_name.m_comp_count != 1)
00267 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir nameComponents != 1");
00268
00269 if (binding.m_binding_type != 1 && binding.m_binding_type != 2)
00270 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir invalid BindingType");
00271
00272
00273 binding.m_ior.AddTap(filecache->m_Dsmcc);
00274
00275 if (pDir && binding.m_name.m_comp_count >= 1)
00276 {
00277 if (strcmp("fil", binding.m_name.m_comps[0].m_kind) == 0)
00278 filecache->AddFileInfo(pDir, &binding);
00279 else if (strcmp("dir", binding.m_name.m_comps[0].m_kind) == 0)
00280 filecache->AddDirInfo(pDir, &binding);
00281 else
00282 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessDir unknown kind %1")
00283 .arg(binding.m_name.m_comps[0].m_kind));
00284 }
00285 }
00286
00287 if ((unsigned)(off - start) != msgbody_len)
00288 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir incorrect msgbody_len");
00289
00290 (*curp) += off;
00291
00292 return true;
00293 }
00294
00295 bool BiopMessage::ProcessFile(DSMCCCacheModuleData *cachep, DSMCCCache *filecache,
00296 unsigned char *data, unsigned long *curp)
00297 {
00298 int off = 0;
00299 const unsigned char *buf = data + (*curp);
00300 unsigned long msgbody_len;
00301 unsigned long content_len;
00302
00303 if (m_objinfo_len != 8)
00304 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessFile objectInfo_length = %1")
00305 .arg(m_objinfo_len));
00306
00307 const unsigned serviceContextList_count = buf[off++];
00308 if (serviceContextList_count)
00309 {
00310 LOG(VB_DSMCC, LOG_WARNING,
00311 QString("[biop] ProcessFile Unexpected serviceContextList_count %1")
00312 .arg(serviceContextList_count));
00313 return false;
00314 }
00315
00316 msgbody_len = ((buf[off ] << 24) | (buf[off + 1] << 16) |
00317 (buf[off + 2] << 8) | (buf[off + 3]));
00318 off += 4;
00319 content_len = ((buf[off ] << 24) | (buf[off + 1] << 16) |
00320 (buf[off + 2] << 8) | (buf[off + 3]));
00321 off += 4;
00322 if (content_len + 4 != msgbody_len)
00323 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessFile incorrect msgbody_len");
00324
00325 (*curp) += off;
00326
00327 DSMCCCacheReference ref(cachep->CarouselId(), cachep->ModuleId(),
00328 cachep->StreamId(), m_objkey);
00329
00330 QByteArray filedata = QByteArray((const char *)data+(*curp), content_len);
00331 filecache->CacheFileData(ref, filedata);
00332
00333 (*curp) += content_len;
00334 return true;
00335 }
00336
00337 void ModuleDescriptorData::Process(const unsigned char *data, int length)
00338 {
00339 while (length > 0)
00340 {
00341 unsigned char tag = *data++;
00342 unsigned char len = *data++;
00343 length -= 2;
00344 switch (tag)
00345 {
00346 case 0x01:
00347 break;
00348 case 0x02:
00349 break;
00350 case 0x03:
00351 break;
00352 case 0x04:
00353 break;
00354 case 0x05:
00355 break;
00356 case 0x06:
00357 break;
00358 case 0x07:
00359 break;
00360 case 0x08:
00361 break;
00362 case 0x09:
00363
00364 isCompressed = true;
00365 originalSize = ((data[1] << 24) | (data[2] << 16) |
00366 (data[3] << 8) | (data[4]));
00367 break;
00368 default:
00369 break;
00370 }
00371 length -= len;
00372 data += len;
00373 }
00374 }
00375
00376 int BiopModuleInfo::Process(const unsigned char *data)
00377 {
00378 int off, ret;
00379 mod_timeout = ((data[0] << 24) | (data[1] << 16) |
00380 (data[2] << 8) | (data[3]));
00381 block_timeout = ((data[4] << 24) | (data[5] << 16) |
00382 (data[6] << 8) | (data[7]));
00383 min_blocktime = ((data[8] << 24) | (data[9] << 16) |
00384 (data[10] << 8) | (data[11]));
00385
00386 taps_count = data[12];
00387 off = 13;
00388
00389 LOG(VB_DSMCC, LOG_DEBUG, QString("[Biop] "
00390 "ModuleTimeout %1 BlockTimeout %2 MinBlockTime %3 Taps %4")
00391 .arg(mod_timeout).arg(block_timeout).arg(min_blocktime)
00392 .arg(taps_count));
00393
00394 if (taps_count > 0)
00395 {
00396
00397 ret = tap.Process(data + off);
00398 if (ret <= 0)
00399 return ret;
00400 off += ret;
00401 }
00402
00403 unsigned userinfo_len = data[off++];
00404
00405 if (userinfo_len > 0)
00406 {
00407 descriptorData.Process(data + off, userinfo_len);
00408 off += userinfo_len;
00409 }
00410 return off;
00411
00412 }
00413
00414 int BiopTap::Process(const unsigned char *data)
00415 {
00416 int off=0;
00417
00418 id = (data[off] << 8) | data[off + 1];
00419 off += 2;
00420 use = (data[off] << 8) | data[off + 1];
00421 off += 2;
00422 assoc_tag = (data[off] << 8) | data[off + 1];
00423 off += 2;
00424 selector_len = data[off++];
00425 selector_data = (char*) malloc(selector_len);
00426 memcpy(selector_data, data + off, selector_len);
00427 if (use == 0x0016)
00428 {
00429 unsigned selector_type = (data[off] << 8) | data[off + 1];
00430 if (selector_len >= 10 && selector_type == 0x0001)
00431 {
00432 off += 2;
00433 unsigned long transactionId = ((data[off] << 24) | (data[off + 1] << 16) |
00434 (data[off + 2] << 8) | (data[off + 3]));
00435 off += 4;
00436 unsigned long timeout = ((data[off] << 24) | (data[off + 1] << 16) |
00437 (data[off + 2] << 8) | (data[off + 3]));
00438 LOG(VB_DSMCC, LOG_DEBUG, QString("[biop] BIOP_DELIVERY_PARA_USE tag %1 id 0x%2 timeout %3uS")
00439 .arg(assoc_tag).arg(transactionId,0,16).arg(timeout));
00440 off += 4;
00441 selector_len -= 10;
00442 }
00443 }
00444
00445 off += selector_len;
00446 return off;
00447 }
00448
00449 int BiopConnbinder::Process(const unsigned char *data)
00450 {
00451 int off = 0, ret;
00452
00453 component_tag = ((data[0] << 24) | (data[1] << 16) |
00454 (data[2] << 8) | (data[3]));
00455 if (0x49534F40 != component_tag)
00456 {
00457 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid Connbinder tag");
00458 return 0;
00459 }
00460 off += 4;
00461 component_data_len = data[off++];
00462 taps_count = data[off++];
00463 if (taps_count > 0)
00464 {
00465
00466 ret = tap.Process(data + off);
00467 #if 0
00468 LOG(VB_GENERAL, LOG_DEBUG, QString("Binder - assoc_tag %1")
00469 .arg(tap.assoc_tag));
00470 #endif
00471 if (ret > 0)
00472 off += ret;
00473
00474 }
00475
00476 return off;
00477 }
00478
00479 int BiopObjLocation::Process(const unsigned char *data)
00480 {
00481 int off = 0;
00482
00483 component_tag = ((data[0] << 24) | (data[1] << 16) |
00484 (data[2] << 8) | (data[3]));
00485 if (0x49534F50 != component_tag)
00486 {
00487 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid ObjectLocation tag");
00488 return 0;
00489 }
00490 off += 4;
00491
00492 component_data_len = data[off++];
00493 m_Reference.m_nCarouselId =
00494 ((data[off ] << 24) | (data[off + 1] << 16) |
00495 (data[off + 2] << 8) | (data[off + 3]));
00496
00497 off += 4;
00498
00499 m_Reference.m_nModuleId = (data[off] << 8) | data[off + 1];
00500 off += 2;
00501
00502 version_major = data[off++];
00503 version_minor = data[off++];
00504 if (1 != version_major || 0 != version_minor)
00505 {
00506 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid ObjectLocation version");
00507 return 0;
00508 }
00509
00510 uint objKeyLen = data[off++];
00511 m_Reference.m_Key = DSMCCCacheKey((char*)data + off, objKeyLen);
00512 off += objKeyLen;
00513 return off;
00514 }
00515
00516
00517
00518 int ProfileBodyLite::Process(const unsigned char * )
00519 {
00520 LOG(VB_DSMCC, LOG_WARNING, "Found LiteProfileBody - Not Implemented Yet");
00521 return 0;
00522 }
00523
00524 int ProfileBodyFull::Process(const unsigned char *data)
00525 {
00526 int off = 0, ret;
00527
00528 data_len = ((data[off ] << 24) | (data[off + 1] << 16) |
00529 (data[off + 2] << 8) | (data[off + 3]));
00530 off += 4;
00531
00532
00533 if (data[off++] != 0)
00534 {
00535 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProfileBody invalid byte order");
00536 return 0;
00537 }
00538
00539 lite_components_count = data[off++];
00540 if (lite_components_count < 2)
00541 {
00542 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProfileBody invalid components_count");
00543 return 0;
00544 }
00545
00546 ret = obj_loc.Process(data + off);
00547 if (ret <= 0)
00548 return ret;
00549 off += ret;
00550
00551 ret = dsm_conn.Process(data + off);
00552 if (ret <= 0)
00553 return ret;
00554 off += ret;
00555
00556 obj_loc.m_Reference.m_nStreamTag = dsm_conn.tap.assoc_tag;
00557
00558
00559
00560 return off;
00561 }
00562
00563 int BiopIor::Process(const unsigned char *data)
00564 {
00565 int off = 0, ret;
00566 type_id_len = ((data[0] << 24) | (data[1] << 16) |
00567 (data[2] << 8) | (data[3]));
00568 type_id = (char*) malloc(type_id_len);
00569 off += 4;
00570 memcpy(type_id, data + off, type_id_len);
00571 off += type_id_len;
00572
00573 tagged_profiles_count = ((data[off ] << 24) | (data[off + 1] << 16) |
00574 (data[off + 2] << 8) | (data[off + 3]));
00575 if (tagged_profiles_count < 1)
00576 {
00577 LOG(VB_DSMCC, LOG_WARNING, "[biop] IOR missing taggedProfile");
00578 return 0;
00579 }
00580 off += 4;
00581
00582 profile_id_tag = ((data[off ] << 24) | (data[off + 1] << 16) |
00583 (data[off + 2] << 8) | (data[off + 3]));
00584 off += 4;
00585
00586 if (profile_id_tag == 0x49534F06)
00587 {
00588 m_profile_body = new ProfileBodyFull;
00589 ret = m_profile_body->Process(data + off);
00590 if (ret <= 0)
00591 return ret;
00592 off += ret;
00593 }
00594 else if(profile_id_tag == 0x49534F05)
00595 {
00596 m_profile_body = new ProfileBodyLite;
00597 ret = m_profile_body->Process(data + off);
00598 if (ret <= 0)
00599 return ret;
00600 off += ret;
00601 }
00602 else
00603 {
00604
00605 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] Unknown Ior profile 0x%1")
00606 .arg(profile_id_tag, 0, 16));
00607 return 0;
00608 }
00609
00610 return off;
00611 }
00612
00613
00614 void BiopIor::AddTap(Dsmcc *pStatus)
00615 {
00616 DSMCCCacheReference *ref = m_profile_body->GetReference();
00617 if (ref != NULL)
00618 pStatus->AddTap(ref->m_nStreamTag, ref->m_nCarouselId);
00619 }
00620
00621 BiopTap::~BiopTap()
00622 {
00623 free(selector_data);
00624 }