📄 dsmcc_biop.cpp
字号:
#include <stdio.h>
#include "../libavcodec/common.h"
#include "dsmcc_biop.h"
template<class T> uint32_t BIOP::add_flat_size(int sum, T flat_object) {
return sum + flat_object.flat_size();
}
bool BIOP::parse(ObjectLocationComponent& component, uint8_t* buffer) {
component.id_tag = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
#ifdef BIOP_STRICT
if(component.id_tag != BIOP_COMPONENT_ID_OBJECTLOC) {
return false;
}
#endif
component.data_length = buffer[4];
component.carousel_id = (buffer[5] << 24) | (buffer[6] << 16) | (buffer[7] << 8) | buffer[8];
component.module_id = (buffer[9] << 8) | buffer[10];
component.version_major = buffer[11];
component.version_minor = buffer[12];
component.object_key_length = buffer[13];
#ifdef BIOP_STRICT
if(component.version_major != 1 || component.version_minor != 0) {
return false;
}
#endif
buffer += 14;
// Hand-crafted for loop; I couldn't bring myself to loop for this triviality
component.object_key = (buffer[0] << 24); if(component.object_key_length > 1) component.object_key |= (buffer[1] << 16); if(component.object_key_length > 2) component.object_key |= (buffer[2] << 8); if(component.object_key_length > 3) component.object_key |= buffer[3];
#ifdef BIOP_TRACE_OBJECTLOCATIONCOMPONENT
BIOP_TRACE_NUM("ObjectLocationComponent", "id_tag", component.id_tag, "8");
BIOP_TRACE_NUM("ObjectLocationComponent", "data_length", component.data_length, "2");
BIOP_TRACE_NUM("ObjectLocationComponent", "carousel_id", component.carousel_id, "8");
BIOP_TRACE_NUM("ObjectLocationComponent", "module_id", component.module_id, "4");
BIOP_TRACE_NUM("ObjectLocationComponent", "version_major", component.version_major, "2");
BIOP_TRACE_NUM("ObjectLocationComponent", "version_minor", component.version_minor, "2");
BIOP_TRACE_NUM("ObjectLocationComponent", "object_key_length", component.object_key_length, "2");
BIOP_TRACE_NUM("ObjectLocationComponent", "object_key", component.object_key, "8");
#endif
return true;
}
bool BIOP::parse(ConnBinderComponent& component, uint8_t* buffer) {
component.id_tag = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
#ifdef BIOP_STRICT
if(component.id_tag != BIOP_COMPONENT_ID_CONNBIND) {
return false;
}
#endif
component.data_length = buffer[4];
component.network_taps_count = buffer[5];
#ifdef BIOP_TRACE_CONNBINDERCOMPONENT
BIOP_TRACE_NUM("ConnBinderComponent", "id_tag", component.id_tag, "8");
BIOP_TRACE_NUM("ConnBinderComponent", "data_length", component.data_length, "2");
BIOP_TRACE_NUM("ConnBinderComponent", "network_taps_count", component.network_taps_count, "2");
#endif
if(component.network_taps_count < 1) {
return false;
}
// Shift the buffer and read the one mandatory tap
buffer += 6;
BIOP_TRACE_INDENT(1);
if(!parse(component.network_tap, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
// Now shift are loop over all other taps to tell us what we 're missing out on
buffer += component.network_tap.flat_size();
BIOP_TRACE_INDENT(1);
for(int i = 1; i < component.network_taps_count; ++i) {
Tap dummy_tap;
if(!parse(dummy_tap, buffer)) {
return false;
}
buffer += dummy_tap.flat_size();
BIOP_TRACE_GENERAL("ConnBinderComponent", "Skipped one network tap beyond the first");
}
BIOP_TRACE_INDENT(-1);
return true;
}
bool BIOP::parse(Tap& tap, uint8_t* buffer) {
// Skip first two bytes (tap.id), it's checked only if BIOP_STRICT
tap.use = (buffer[2] << 8) | buffer[3];
tap.assoc_tag = (buffer[4] << 8) | buffer[5];
tap.selector_length = buffer[6];
#ifdef BIOP_TRACE_TAP
BIOP_TRACE_NUM("Tap", "id", ((buffer[0] << 8) | buffer[1]), "4");
BIOP_TRACE_NUM("Tap", "use", tap.use, "4");
BIOP_TRACE_NUM("Tap", "association_tag", tap.assoc_tag, "4");
BIOP_TRACE_NUM("Tap", "selector_length", tap.selector_length, "2");
#endif
#ifdef BIOP_STRICT
if(((buffer[0] << 8) | buffer[1]) != 0x00) { // mandatory per ETSI TR 101 202
return false;
}
switch(tap.use) { // all this mandatory per ETSI TR 101 202
case BIOP_DELIVERY_PARA_USE:
if(tap.selector_length != 0x0a) {
return false;
}
break;
case BIOP_PROGRAM_USE:
case BIOP_OBJECT_USE:
if(tap.selector_length != 0) {
return false;
}
break;
default:
return true;
}
#endif
if(tap.selector_length) {
tap.selector.type = (buffer[7] << 8) | buffer[8];
tap.selector.transaction_id = (buffer[9] << 24) | (buffer[10] << 16) | (buffer[11] << 8) | buffer[12];
tap.selector.timeout = (buffer[13] << 24) | (buffer[14] << 16) | (buffer[15] << 8) | buffer[16];
#ifdef BIOP_TRACE_TAP
BIOP_TRACE_NUM("Tap", "selector.type", tap.selector.type, "4");
BIOP_TRACE_NUM("Tap", "selector.transaction_id", tap.selector.transaction_id, "8");
BIOP_TRACE_NUM("Tap", "selector.timeout", tap.selector.timeout, "8");
#endif
#ifdef BIOP_STRICT
if(tap.selector.type != 0x0001) { // guess what?
return false;
}
#endif
}
return true;
}
bool BIOP::parse(ServiceGatewayInfo& sgi, uint8_t* buffer) {
BIOP_TRACE_THRESHOLD(-1);
BIOP_TRACE_INDENT(1);
if(!parse(sgi.ior, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(((sgi.ior.type_id[0] << 24) | (sgi.ior.type_id[1] << 16) | (sgi.ior.type_id[2] << 8) | sgi.ior.type_id[3]) != BIOP_ALIAS_TYPE_ID_SRG) {
return false;
}
#endif
buffer += sgi.ior.flat_size();
sgi.download_taps_count = buffer[0];
++buffer;
BIOP_TRACE_INDENT(1);
for(int i = 0; i < sgi.download_taps_count; ++i) {
Tap dummy_tap;
if(!parse(dummy_tap, buffer)) {
return false;
}
buffer += dummy_tap.flat_size();
BIOP_TRACE_GENERAL("ServiceGatewayInfo", "Skipped one network tap");
}
BIOP_TRACE_INDENT(-1);
sgi.service_context_list_count = buffer[0];
++buffer;
BIOP_TRACE_INDENT(1);
for(int i = 0; i < sgi.service_context_list_count; ++i) {
ServiceContext dummy_context;
if(!parse(dummy_context, buffer)) {
return false;
}
buffer += dummy_context.flat_size();
BIOP_TRACE_GENERAL("ServiceGatewayInfo", "Skipped one service context");
}
BIOP_TRACE_INDENT(-1);
sgi.user_info_length = (buffer[0] << 8) | buffer[1];
#ifdef BIOP_TRACE_SERVICEGATEWAYINFO
BIOP_TRACE_NUM("ServiceGatewayInfo", "download_taps_count", sgi.download_taps_count, "2");
BIOP_TRACE_NUM("ServiceGatewayInfo", "service_context_list_count", sgi.service_context_list_count, "2");
BIOP_TRACE_NUM("ServiceGatewayInfo", "user_info_length", sgi.user_info_length, "2");
#endif
BIOP_TRACE_THRESHOLD(10);
return true;
}
bool BIOP::parse(ModuleInfo& mi, uint8_t* buffer) {
mi.z_compression_method = mi.z_original_size = 0;
mi.module_timeout = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
mi.block_timeout = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
mi.min_block_time = (buffer[8] << 24) | (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
mi.taps_count = buffer[12];
if(mi.taps_count != 1) {
return false;
}
BIOP_TRACE_INDENT(1);
if(!parse(mi.tap, buffer + 13)) {
return false;
}
BIOP_TRACE_INDENT(-1);
mi.user_info_length = buffer[20];
buffer += 21;
int i = 0;
while(i < mi.user_info_length) {
uint8_t descriptor_tag = buffer[i++];
uint8_t descriptor_len = buffer[i++];
switch(descriptor_tag) {
case 0x09: // compressed module descriptor
mi.z_compression_method = buffer[i];
mi.z_original_size = (buffer[i+1] << 24) | (buffer[i+2] << 16) | (buffer[i+3] << 8) | buffer[i+4];
break;
default:
printf(">> descriptor_tag: %02x\n", descriptor_tag);
return false;
break;
}
i += descriptor_len;
}
return true;
}
bool BIOP::parse(DIIModuleLoopItem& module, uint8_t* buffer) {
module.module_id = (buffer[0] << 8) | buffer[1]; module.module_size = (buffer[2] << 24) | (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]; module.module_version = buffer[6]; module.module_info_length = buffer[7];
#ifdef BIOP_TRACE_DIIMODULELOOPITEM
BIOP_TRACE_NUM("DIIModuleLoopItem", "module_id", module.module_id, "4");
BIOP_TRACE_NUM("DIIModuleLoopItem", "module_size", module.module_size, "8");
BIOP_TRACE_NUM("DIIModuleLoopItem", "module_version", module.module_version, "2");
BIOP_TRACE_NUM("DIIModuleLoopItem", "module_info_length", module.module_info_length, "2");
#endif
BIOP_TRACE_INDENT(1);
if(!parse(module.module_info, buffer + 8)) {
return false;
}
BIOP_TRACE_INDENT(-1);
return true;
}
bool BIOP::parse(DirectoryMessage& dm, uint8_t* buffer) {
BIOP_TRACE_INDENT(1);
if(!parse(dm.header, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(dm.header.object_kind != BIOP_ALIAS_TYPE_ID_DIR) {
return false;
}
#endif
buffer += dm.header.flat_size();
uint16_t bindings_count = (buffer[0] << 8) | buffer[1];
dm.bindings.resize(bindings_count);
#ifdef BIOP_TRACE_DIRECTORYMESSAGE
BIOP_TRACE_NUM("DirectoryMessage", "bindings_count", bindings_count, "4");
#endif
// Reposition the buffer to start reading bindings
buffer += 2;
BIOP_TRACE_INDENT(1);
for(uint16_t i = 0; i < bindings_count; ++i) {
BIOP::Binding bind;
if(!parse(bind, buffer)) {
return false;
}
dm.bindings[i] = bind;
buffer += bind.flat_size();
}
BIOP_TRACE_INDENT(-1);
return true;
}
bool BIOP::parse(FileMessage& fm, uint8_t* buffer) {
BIOP_TRACE_INDENT(1);
if(!parse(fm.header, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(fm.header.object_kind != BIOP_ALIAS_TYPE_ID_FIL) {
return false;
}
#endif
fm.contents = buffer + fm.header.flat_size() + 4;
return true;
}
bool BIOP::parse(ServiceGateway& srg, uint8_t* buffer) {
BIOP_TRACE_INDENT(1);
if(!parse(srg.header, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(srg.header.object_kind != BIOP_ALIAS_TYPE_ID_SRG) {
return false;
}
#endif
buffer += srg.header.flat_size();
uint16_t bindings_count = (buffer[0] << 8) | buffer[1];
srg.bindings.resize(bindings_count);
#ifdef BIOP_TRACE_SERVICEGATEWAY
BIOP_TRACE_NUM("ServiceGateway", "bindings_count", bindings_count, "4");
#endif
// Reposition the buffer to start reading bindings
buffer += 2;
BIOP_TRACE_INDENT(1);
for(uint16_t i = 0; i < bindings_count; ++i) {
BIOP::Binding bind;
if(!parse(bind, buffer)) {
return false;
}
srg.bindings[i] = bind;
buffer += bind.flat_size();
}
BIOP_TRACE_INDENT(-1);
return true;
}
bool BIOP::parse(StreamMessage& str, uint8_t* buffer) {
BIOP_TRACE_INDENT(1);
if(!parse(str.header, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(str.header.object_kind != BIOP_ALIAS_TYPE_ID_STR) {
return false;
}
#endif
buffer += str.header.flat_size();
uint8_t taps_count = buffer[0];
#ifdef BIOP_TRACE_STREAMMESSAGE
BIOP_TRACE_NUM("StreamMessage", "taps_count", taps_count, "2");
#endif
if(taps_count < 1) {
return false;
}
// Shift the buffer and read the one mandatory tap
++buffer;
BIOP_TRACE_INDENT(1);
if(!parse(str.tap, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
#ifdef BIOP_STRICT
if(str.tap.use != BIOP_PROGRAM_USE) {
return false;
}
#endif
// Now shift are loop over all other taps to tell us what we 're missing out on
buffer += str.tap.flat_size();
BIOP_TRACE_INDENT(1);
for(uint8_t i = 1; i < taps_count; ++i) {
Tap dummy_tap;
if(!parse(dummy_tap, buffer)) {
return false;
}
buffer += dummy_tap.flat_size();
BIOP_TRACE_GENERAL("StreamMessage", "Skipped one tap beyond the first");
}
BIOP_TRACE_INDENT(-1);
return true;
}
bool BIOP::parse(StreamEventMessage& ste, uint8_t* buffer) {
BIOP_TRACE_INDENT(1);
if(!parse(ste.header, buffer)) {
return false;
}
BIOP_TRACE_INDENT(-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -