📄 dsmcc.h
字号:
if(!download_trackers.contains(profile.object_location.carousel_id)) {
#ifdef DSM_CC_TRACE_CAROUSELTRACKER
DSM_CC_TRACE_NUM("CarouselTracker", "DSI received for previously unknown download_id", profile.object_location.carousel_id, "8");
#endif
#ifdef DSM_CC_STRICT
if(profile.conn_binder.network_tap.selector_length == 0) {
DSM_CC_TRACE_GENERAL("CarouselTracker", "ERROR: IOR pointing to SRG: tap does not define a transaction_id!");
return false;
}
#endif
// Start tracking this download
if(!Track(profile.object_location.carousel_id, table_id_ext)) {
return false;
}
// Now, start tracking the module which contains the service gateway
if(!download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id)) {
return false;
}
#ifdef DSM_CC_TRACE_CAROUSELTRACKER
DSM_CC_TRACE_NUM("CarouselTracker", "Signalling we 're interested in the SRG, transaction_id", profile.conn_binder.network_tap.selector.transaction_id, "8");
#endif
// Note down that we want to receive the download control messages containing the DII
RequestDownloadControl(component_tag, profile.conn_binder.network_tap.selector.transaction_id);
// Note down that when the DII has been received, enabling us to get the data blocks, and
// the data blocks are received and examined, we are interested in the service gateway object
MarkObject(profile.object_location.carousel_id,
profile.object_location.module_id,
profile.object_location.object_key,
profile.object_location.object_key_length,
true);
return true;
}
/*
printf("For this carousel, we have requested %d objects. %d total have arrived, %d premature.\n",
download_stats[profile.object_location.carousel_id].objects_requested,
download_stats[profile.object_location.carousel_id].objects_arrived,
download_stats[profile.object_location.carousel_id].objects_premature
);
*/
// OK, we already have this download_id, maybe the carousel has been updated?
// Remember, every time the carousel is updated, table_id_ext toggles between 0x0000 and 0x0001
if(download_stats[profile.object_location.carousel_id].last_table_id_ext != table_id_ext) {
dsmcc_trace("[CarouselTracker] Updated DSI received for download_id = 0x%08x\n", profile.object_location.carousel_id);
return Reset(profile.object_location.carousel_id, table_id_ext);
}
return true;
}
bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::ServiceGateway& srg) {
if(download_stats.contains(download_id)) {
++download_stats[download_id].objects_arrived;
}
if(!InterestedInObject(download_id, module_id, srg.header)) {
++download_stats[download_id].objects_premature;
return false;
}
tracked_module_t module = ModuleGetParameters(download_id, module_id);
// Commit to permanent storage
if(!StoreObject(download_id, module_id, module.module_version, srg)) {
return false;
}
uint32_t num_bindings = srg.bindings.size();
for(uint32_t i = 0; i < num_bindings; ++i) {
if(srg.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
continue;
}
BIOP::BIOPProfile profile = srg.bindings[i].ior.profiles[0].biop;
// We have to:
// 1. Signal we want to receive transaction_ids for the messages describing the module containing this object
// 2. Start tracking this module, if we aren't already tracking it
// 3. Mark the object at the end of the module as interesting
RequestDownloadControl(profile.conn_binder.network_tap.assoc_tag, profile.conn_binder.network_tap.selector.transaction_id);
download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id);
MarkObject(profile.object_location.carousel_id,
profile.object_location.module_id,
profile.object_location.object_key,
profile.object_location.object_key_length,
true);
}
download_stats[download_id].objects_requested += num_bindings;
return true;
}
bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::DirectoryMessage& dm) {
if(download_stats.contains(download_id)) {
++download_stats[download_id].objects_arrived;
}
if(!InterestedInObject(download_id, module_id, dm.header)) {
++download_stats[download_id].objects_premature;
return false;
}
uint32_t num_bindings = dm.bindings.size();
tracked_module_t module = ModuleGetParameters(download_id, module_id);
// Commit to permanent storage
if(!StoreObject(download_id, module_id, module.module_version, dm)) {
return false;
}
// Same story as with ServiceGateway
for(uint32_t i = 0; i < num_bindings; ++i) {
if(dm.bindings[i].ior.profiles[0].id_tag != BIOP_PROFILE_ID_BIOP) {
continue;
}
BIOP::BIOPProfile profile = dm.bindings[i].ior.profiles[0].biop;
// We have to:
// 1. Signal we want to receive transaction_ids for the messages describing the module containing this object
// 2. Start tracking this module, if we aren't already tracking it
// 3. Mark the object at the end of the module as interesting
RequestDownloadControl(profile.conn_binder.network_tap.assoc_tag, profile.conn_binder.network_tap.selector.transaction_id);
download_trackers[profile.object_location.carousel_id]->TrackModule(profile.object_location.module_id);
MarkObject(profile.object_location.carousel_id,
profile.object_location.module_id,
profile.object_location.object_key,
profile.object_location.object_key_length,
true);
}
download_stats[download_id].objects_requested += num_bindings;
return true;
}
bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::FileMessage& fm) {
if(download_stats.contains(download_id)) {
++download_stats[download_id].objects_arrived;
}
if(!InterestedInObject(download_id, module_id, fm.header)) {
++download_stats[download_id].objects_premature;
return false;
}
tracked_module_t module = ModuleGetParameters(download_id, module_id);
// Commit to permanent storage
return StoreObject(download_id, module_id, module.module_version, fm);
}
bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::StreamMessage& str) {
return false;
}
bool ObjectArrived(uint32_t download_id, uint16_t module_id, const BIOP::StreamEventMessage& ste) {
return false;
}
void RequestDownloadControl(uint8_t component_tag, uint32_t tr_id) {
// We 're going to call MarkDownloadControl, but first cut off
// the "version" part of the transaction_id. This way, when we
// receive the first DII message it is guaranteed to have a
// different version field than 0x0000 and it will be accepted.
MarkDownloadControl(component_tag, tr_id & 0xffff, BIOP::REQUESTED);
}
void MarkObject(uint32_t download_id, uint16_t module_id, uint32_t object_key, uint8_t object_key_length, bool mark) {
if(!download_trackers.contains(download_id)) {
return;
}
download_trackers[download_id]->MarkObject(module_id, object_key, object_key_length, mark);
}
void MarkDownloadControl(uint8_t component_tag, uint32_t tr_id, BIOP::ObjectStatus status) {
#ifdef DSM_CC_TRACE_CAROUSELTRACKER
//printf("[DSMCC::CarouselTracker] Marking download control message: assoc_tag = 0x%02x, transaction_id = 0x%08x, status = %d\n", component_tag, tr_id, status);
#endif
control_message_trackers[component_tag].SetStatus(tr_id, status);
}
void MarkDownloadData(uint8_t component_tag, BIOP::ObjectStatus status) {
if(data_message_trackers[component_tag] == BIOP::UNKNOWN && status != BIOP::UNKNOWN) {
streams_needed.push_back(component_tag);
}
data_message_trackers[component_tag] = status;
}
bool InterestedInDownloadControl(uint8_t component_tag, uint32_t tr_id) {
// First off, the two LSBs are the identification. We don't want our
// identification to be foiled by the value of the very last bit
// (update flag), so set that to 1 to make the equality checks easier.
uint16_t id = (tr_id & 0xffff) | 1;
// The two MSBs are versioning
uint16_t version = (tr_id & 0xffff0000) >> 16;
if(id == 0x0001) {
// Always interested in DSI messages to catch carousel updates
return true;
}
if(!control_message_trackers.contains(component_tag)) {
// Nothing wanted with this component tag
return false;
}
if(control_message_trackers[component_tag].GetVersion(tr_id) == version) {
// Old news
return false;
}
return control_message_trackers[component_tag].GetStatus(tr_id) != BIOP::UNKNOWN;
}
bool InterestedInDownloadData(uint8_t component_tag) {
return data_message_trackers[component_tag] != BIOP::UNKNOWN;
}
bool InterestedInObject(uint32_t download_id, uint16_t module_id, uint32_t object_key, uint8_t key_length) {
if(!download_trackers.contains(download_id)) {
return false;
}
return download_trackers[download_id]->InterestedInObject(module_id, object_key, key_length);
}
bool InterestedInObject(uint32_t download_id, uint16_t module_id, const BIOP::MessageHeader& header) {
uint32_t object_key(0); uint8_t key_size(header.object_key.size()); // Hand-crafted for loop; I couldn't bring myself to loop for this triviality object_key |= (header.object_key[0] << 24); if(key_size > 1) object_key |= (header.object_key[1] << 16); if(key_size > 2) object_key |= (header.object_key[2] << 8); if(key_size > 3) object_key |= header.object_key[3];
return InterestedInObject(download_id, module_id, object_key, key_size);
}
private:
typedef struct download_stats {
uint16_t last_table_id_ext;
uint32_t objects_requested;
uint32_t objects_arrived;
uint32_t objects_premature;
download_stats() : objects_requested(0), objects_arrived(0), objects_premature(0) {}
} download_stats_t;
// This holds the download trackers themselves, indexed by download_id
typedef QMap<uint32_t, DownloadTracker*> download_tracker_map;
download_tracker_map download_trackers;
// This holds information pertinent to the state of each download tracker,
// even though we could do without it (it's not necessary for correct
// operation), indexed by download_id
typedef QMap<uint32_t, download_stats_t> download_stats_map;
download_stats_map download_stats;
// This holds information about the download control messages (DIIs)
// that we are interested in receiving (or not). A message won't get
// forwarded to a download tracker unless the DownloadMessageTracker
// thinks it's interesting. This is done mainly to avoid the extra
// overhead of parsing messages that are of no use to us.
// Indexed by stream component_tag.
typedef QMap<uint8_t, DownloadControlTracker> download_control_map;
download_control_map control_message_trackers;
// This would do the same for DDB messages, however DDB messages have
// to be parsed before we can know if we 're interested in them. So
// this takes the form of an array indexed by component_tag, telling
// us if we should be bothering with DDBs from that stream at all.
uint8_t* data_message_trackers;
// An array to hold identification for the streams we need to start
// receiving. Presently just component_tag. Not a stack because
// std::stack is just a container adapter anyway.
std::vector<uint8_t> streams_needed;
};
bool parse(DownloadDataBlock& block, uint8_t* buffer);
bool parse(DownloadInfoIndication& dii, uint8_t* buffer);
bool parse(MessageHeader& header, uint8_t* buffer);
void sink(...); // used to sink printf() args when trace is turned off
}
#endif // DSMCC_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -