MythTV master
dsmccbiop.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) David C.J. Matthews 2005, 2006
3 * Derived from libdsmcc by Richard Palmer
4 */
5#include <cstdlib>
6#include <cstring>
7
9
10#include "dsmccbiop.h"
11#include "dsmccreceiver.h"
12#include "dsmcccache.h"
13#include "dsmccobjcarousel.h"
14#include "dsmcc.h"
15
16int BiopNameComp::Process(const unsigned char *data)
17{
18 int off = 0;
19
20 uint len = data[off++];
21 m_id = std::string((char*)data + off, len);
22
23 off += len;
24 len = data[off++];
25 m_kind = std::string((char*)data + off, len);
26
27 off += len;
28
29 // Remove any NUL characters at the end
30 while (!m_id.empty() && (m_id.back() == 0))
31 m_id.pop_back();
32 while (!m_kind.empty() && (m_kind.back() == 0))
33 m_kind.pop_back();
34
35 return off;
36}
37
39{
40 delete[] m_comps;
41}
42
43int BiopName::Process(const unsigned char *data)
44{
45 int off = 0;
46 m_compCount = data[0];
47
48 if (m_compCount != 1)
49 LOG(VB_DSMCC, LOG_WARNING, "[biop] Expected one name");
50
51 off++;
53
54 for (int i = 0; i < m_compCount; i++)
55 {
56 int ret = m_comps[i].Process(data + off);
57 if (ret <= 0)
58 return ret;
59 off += ret;
60 }
61
62 return off;
63}
64
65int BiopBinding::Process(const unsigned char *data)
66{
67 int off = 0;
68 int ret = m_name.Process(data);
69
70 if (ret > 0)
71 off += ret;
72 else
73 return ret; // Error
74
75 m_bindingType = data[off++];
76 ret = m_ior.Process(data + off);
77
78 if (ret > 0)
79 off += ret;
80 else
81 return ret; // Error
82
83 uint len = (data[off] << 8) | data[off + 1];
84 off += 2;
85
86 if (len > 0)
87 m_objInfo = std::vector<uint8_t>(data + off, data + off + len);
88 else
89 m_objInfo.clear();
90
91 off += len;
92
93 return off;
94}
95
97 unsigned char *data, unsigned long *curp)
98{
99 // Parse header
100 if (! ProcessMsgHdr(data, curp))
101 {
102 LOG(VB_DSMCC, LOG_ERR,
103 "[biop] Invalid biop header, dropping rest of module");
104
105 /* not valid, skip rest of data */
106 return false;
107 }
108
109 // Handle each message type
110 if (m_objKind == "fil")
111 {
112 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing file");
113 return ProcessFile(cachep, filecache, data, curp);
114 }
115 if (m_objKind == "dir")
116 {
117 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing directory");
118 return ProcessDir(false, cachep, filecache, data, curp);
119 }
120 if (m_objKind == "srg")
121 {
122 LOG(VB_DSMCC, LOG_DEBUG, "[biop] Processing gateway");
123 return ProcessDir(true, cachep, filecache, data, curp);
124 }
125
126 /* Error */
127 LOG(VB_DSMCC, LOG_WARNING, QString("Unknown or unsupported format %1%2%3%4")
128 .arg(m_objKind[0]).arg(m_objKind[1])
129 .arg(m_objKind[2]).arg(m_objKind[3]));
130 return false;
131}
132
133bool BiopMessage::ProcessMsgHdr(const unsigned char *data, unsigned long *curp)
134{
135 const unsigned char *buf = data + (*curp);
136 int off = 0;
137
138 if (buf[off] !='B' || buf[off +1] !='I' || buf[off +2] !='O' || buf[off +3] !='P')
139 {
140 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage - invalid header");
141 return false;
142 }
143 off += 4;
144
145 m_versionMajor = buf[off++];
146 m_versionMinor = buf[off++];
147 if (m_versionMajor != 1 || m_versionMinor != 0)
148 {
149 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid version");
150 return false;
151 }
152
153 if (buf[off++] != 0)
154 {
155 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid byte order");
156 return false;
157 }
158 if (buf[off++] != 0)
159 {
160 LOG(VB_DSMCC, LOG_WARNING, "BiopMessage invalid message type");
161 return false;
162 }
163
164 m_messageSize = COMBINE32(buf, off);
165 off += 4;
166
167 uint len = buf[off++];
168 m_objKey = DSMCCCacheKey((const char*)buf + off, len);
169 off += len;
170
171 len = COMBINE32(buf, off);
172 off += 4;
173 m_objKind = std::string((char*)buf + off, len);
174 // Strip NUL characters from the end
175 while (!m_objKind.empty() && (m_objKind.back() == 0))
176 m_objKind.pop_back();
177 off += len;
178
179 len = buf[off] << 8 | buf[off + 1];
180 off += 2;
181 m_objInfo = std::vector<uint8_t>(buf + off, buf + off + len);
182 off += len;
183
184 (*curp) += off;
185
186 return true;
187}
188
189
199 bool isSrg, DSMCCCacheModuleData *cachep, DSMCCCache *filecache,
200 const unsigned char *data, unsigned long *curp)
201{
202 int off = 0;
203 const unsigned char * const buf = data + (*curp);
204
205 if (!m_objInfo.empty())
206 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir non-zero objectInfo_length");
207
208 const unsigned serviceContextList_count = buf[off++];
209 if (serviceContextList_count)
210 {
211 // TODO Handle serviceContextList for service gateway
212 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessDir serviceContextList count %1")
213 .arg(serviceContextList_count));
214 return false; // Error
215 }
216
217 unsigned long msgbody_len = COMBINE32(buf, off);
218 off += 4;
219 int const start = off;
220
221 unsigned int bindings_count = buf[off] << 8 | buf[off + 1];
222 off += 2;
223
224 DSMCCCacheReference ref(cachep->CarouselId(), cachep->ModuleId(),
225 cachep->StreamId(), m_objKey);
226 DSMCCCacheDir *pDir = isSrg ? filecache->Srg(ref) : filecache->Directory(ref);
227
228 for (uint i = 0; i < bindings_count; i++)
229 {
230 BiopBinding binding;
231 int ret = binding.Process(buf + off);
232 if (ret > 0)
233 off += ret;
234 else
235 return false; // Error
236
237 if (binding.m_name.m_compCount != 1)
238 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir nameComponents != 1");
239
240 if (binding.m_bindingType != 1 && binding.m_bindingType != 2)
241 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir invalid BindingType");
242
243 // Process any taps in this binding.
244 binding.m_ior.AddTap(filecache->m_dsmcc);
245
246 if (pDir && binding.m_name.m_compCount >= 1)
247 {
248 if ("fil" == binding.m_name.m_comps[0].m_kind)
249 DSMCCCache::AddFileInfo(pDir, &binding);
250 else if ("dir" == binding.m_name.m_comps[0].m_kind)
251 DSMCCCache::AddDirInfo(pDir, &binding);
252 else
253 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessDir unknown kind %1")
254 .arg(QString::fromStdString(binding.m_name.m_comps[0].m_kind)));
255 }
256 }
257
258 if ((unsigned)(off - start) != msgbody_len)
259 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessDir incorrect msgbody_len");
260
261 (*curp) += off;
262
263 return true;
264}
265
267 unsigned char *data, unsigned long *curp)
268{
269 int off = 0;
270 const unsigned char *buf = data + (*curp);
271
272 if (m_objInfo.size() != 8)
273 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] ProcessFile objectInfo_length = %1")
274 .arg(m_objInfo.size()));
275
276 const unsigned serviceContextList_count = buf[off++];
277 if (serviceContextList_count)
278 {
279 LOG(VB_DSMCC, LOG_WARNING,
280 QString("[biop] ProcessFile Unexpected serviceContextList_count %1")
281 .arg(serviceContextList_count));
282 return false; // Error
283 }
284
285 unsigned long msgbody_len = COMBINE32(buf, off);
286 off += 4;
287 unsigned long content_len = COMBINE32(buf, off);
288 off += 4;
289 if (content_len + 4 != msgbody_len)
290 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProcessFile incorrect msgbody_len");
291
292 (*curp) += off;
293
294 DSMCCCacheReference ref(cachep->CarouselId(), cachep->ModuleId(),
295 cachep->StreamId(), m_objKey);
296
297 QByteArray filedata = QByteArray((const char *)data+(*curp), content_len);
298 filecache->CacheFileData(ref, filedata);
299
300 (*curp) += content_len;
301 return true;
302}
303
304void ModuleDescriptorData::Process(const unsigned char *data, int length)
305{
306 while (length > 0)
307 {
308 unsigned char tag = *data++;
309 unsigned char len = *data++;
310 length -= 2;
311
312 // Tags:
313 // case 0x01: // Type
314 // case 0x02: // Name
315 // case 0x03: // Info
316 // case 0x04: // Modlink
317 // case 0x05: // CRC
318 // case 0x06: // Location
319 // case 0x07: // DLtime
320 // case 0x08: // Grouplink
321 // case 0x09: // Compressed.
322 if (tag == 0x09)
323 {
324 // Skip the method.
325 m_isCompressed = true;
326 m_originalSize = COMBINE32(data, 1);
327 }
328
329 length -= len;
330 data += len;
331 }
332}
333
334int BiopModuleInfo::Process(const unsigned char *data)
335{
336 m_modTimeout = COMBINE32(data, 0);
337 m_blockTimeout = COMBINE32(data, 4);
338 m_minBlockTime = COMBINE32(data, 8);
339
340 m_tapsCount = data[12];
341 int off = 13;
342
343 LOG(VB_DSMCC, LOG_DEBUG, QString("[Biop] "
344 "ModuleTimeout %1 BlockTimeout %2 MinBlockTime %3 Taps %4")
346 .arg(m_tapsCount));
347
348 if (m_tapsCount > 0)
349 {
350 /* only 1 allowed TODO - may not be first though ? */
351 int ret = m_tap.Process(data + off);
352 if (ret <= 0)
353 return ret;
354 off += ret;
355 }
356
357 unsigned userinfo_len = data[off++];
358
359 if (userinfo_len > 0)
360 {
361 m_descriptorData.Process(data + off, userinfo_len);
362 off += userinfo_len;
363 }
364 return off;
365
366}
367
368int BiopTap::Process(const unsigned char *data)
369{
370 int off=0;
371
372 m_id = (data[off] << 8) | data[off + 1]; // Ignored
373 off += 2;
374 m_use = (data[off] << 8) | data[off + 1];
375 off += 2;
376 m_assocTag = (data[off] << 8) | data[off + 1];
377 off += 2;
378 uint selectorLen = data[off++];
379 m_selector = std::vector<uint8_t>(data + off, data + off + selectorLen);
380 if (m_use == 0x0016) // BIOP_DELIVERY_PARA_USE
381 {
382 unsigned selector_type = (data[off] << 8) | data[off + 1];
383 if (selectorLen >= 10 && selector_type == 0x0001)
384 {
385 off += 2;
386 unsigned long transactionId = COMBINE32(data, off);
387 off += 4;
388 unsigned long timeout = COMBINE32(data, off);
389 LOG(VB_DSMCC, LOG_DEBUG, QString("[biop] BIOP_DELIVERY_PARA_USE tag %1 id 0x%2 timeout %3uS")
390 .arg(m_assocTag).arg(transactionId,0,16).arg(timeout));
391 off += 4;
392 selectorLen -= 10;
393 }
394 }
395
396 off += selectorLen;
397 return off;
398}
399
400int BiopConnbinder::Process(const unsigned char *data)
401{
402 int off = 0;
403
404 m_componentTag = COMBINE32(data, 0);
405 if (0x49534F40 != m_componentTag)
406 {
407 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid Connbinder tag");
408 return 0;
409 }
410 off += 4;
411 m_componentDataLen = data[off++];
412 m_tapsCount = data[off++];
413 if (m_tapsCount > 0)
414 {
415 /* UKProfile - only first tap read */
416 int ret = m_tap.Process(data + off);
417#if 0
418 LOG(VB_GENERAL, LOG_DEBUG, QString("Binder - assoc_tag %1")
419 .arg(m_tap.m_assocTag));
420#endif
421 if (ret > 0)
422 off += ret;
423 /* else TODO error */
424 }
425
426 return off;
427}
428
429int BiopObjLocation::Process(const unsigned char *data)
430{
431 int off = 0;
432
433 m_componentTag = COMBINE32(data, 0);
434 if (0x49534F50 != m_componentTag)
435 {
436 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid ObjectLocation tag");
437 return 0;
438 }
439 off += 4;
440
441 m_componentDataLen = data[off++];
443
444 off += 4;
445
446 m_reference.m_nModuleId = (data[off] << 8) | data[off + 1];
447 off += 2;
448
449 m_versionMajor = data[off++];
450 m_versionMinor = data[off++];
451 if (1 != m_versionMajor || 0 != m_versionMinor)
452 {
453 LOG(VB_DSMCC, LOG_WARNING, "[biop] Invalid ObjectLocation version");
454 return 0;
455 }
456
457 uint objKeyLen = data[off++]; /* <= 4 */
458 m_reference.m_key = DSMCCCacheKey((char*)data + off, objKeyLen);
459 off += objKeyLen;
460 return off;
461}
462
463// A Lite profile body is used to refer to an object referenced through
464// a different PMT, We don't support that, at least at the moment.
465int ProfileBodyLite::Process(const unsigned char * /*data*/)
466{
467 LOG(VB_DSMCC, LOG_WARNING, "Found LiteProfileBody - Not Implemented Yet");
468 return 0;
469}
470
471int ProfileBodyFull::Process(const unsigned char *data)
472{
473 int off = 0;
474
475 m_dataLen = COMBINE32(data, off);
476 off += 4;
477
478 /* bit order */
479 if (data[off++] != 0)
480 {
481 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProfileBody invalid byte order");
482 return 0;
483 }
484
485 m_liteComponentsCount = data[off++];
486 if (m_liteComponentsCount < 2)
487 {
488 LOG(VB_DSMCC, LOG_WARNING, "[biop] ProfileBody invalid components_count");
489 return 0;
490 }
491
492 int ret = m_objLoc.Process(data + off);
493 if (ret <= 0)
494 return ret;
495 off += ret;
496
497 ret = m_dsmConn.Process(data + off);
498 if (ret <= 0)
499 return ret;
500 off += ret;
501
503
504 /* UKProfile - ignore anything else */
505
506 return off;
507}
508
509int BiopIor::Process(const unsigned char *data)
510{
511 int off = 0;
512 uint len = COMBINE32(data, 0);
513 off += 4;
514 m_typeId = std::string((char*)data + off, len);
515 // Strip NUL characters from the end
516 while (!m_typeId.empty() && (m_typeId.back() == 0))
517 m_typeId.pop_back();
518 off += len;
519
520 m_taggedProfilesCount = COMBINE32(data, off);
521 if (m_taggedProfilesCount < 1)
522 {
523 LOG(VB_DSMCC, LOG_WARNING, "[biop] IOR missing taggedProfile");
524 return 0;
525 }
526 off += 4;
527
528 m_profileIdTag = COMBINE32(data, off);
529 off += 4;
530
531 if (m_profileIdTag == 0x49534F06) // profile_id_tag == 0x49534F06
532 {
534 int ret = m_profileBody->Process(data + off);
535 if (ret <= 0)
536 return ret;
537 off += ret;
538 }
539 else if(m_profileIdTag == 0x49534F05) // profile_id_tag == 0x49534F05
540 {
542 int ret = m_profileBody->Process(data + off);
543 if (ret <= 0)
544 return ret;
545 off += ret;
546 }
547 else
548 {
549 /* UKProfile - receiver may ignore other profiles */
550 LOG(VB_DSMCC, LOG_WARNING, QString("[biop] Unknown Ior profile 0x%1")
551 .arg(m_profileIdTag, 0, 16));
552 return 0;
553 }
554
555 return off;
556}
557
558// An IOR may refer to other streams. We may have to add taps for them.
559void BiopIor::AddTap(Dsmcc *pStatus) const
560{
562 if (ref != nullptr)
563 pStatus->AddTap(ref->m_nStreamTag, ref->m_nCarouselId);
564}
BiopName m_name
Definition: dsmccbiop.h:154
std::vector< uint8_t > m_objInfo
Definition: dsmccbiop.h:157
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:65
char m_bindingType
Definition: dsmccbiop.h:155
BiopIor m_ior
Definition: dsmccbiop.h:156
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:400
unsigned long m_componentTag
Definition: dsmccbiop.h:64
unsigned char m_tapsCount
Definition: dsmccbiop.h:66
BiopTap m_tap
Definition: dsmccbiop.h:67
unsigned char m_componentDataLen
Definition: dsmccbiop.h:65
void AddTap(Dsmcc *pStatus) const
Definition: dsmccbiop.cpp:559
unsigned long m_taggedProfilesCount
Definition: dsmccbiop.h:139
std::string m_typeId
Definition: dsmccbiop.h:138
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:509
unsigned long m_profileIdTag
Definition: dsmccbiop.h:140
ProfileBody * m_profileBody
Definition: dsmccbiop.h:141
bool ProcessDir(bool isSrg, DSMCCCacheModuleData *cachep, DSMCCCache *cache, const unsigned char *data, unsigned long *curp)
Process a Directory message.
Definition: dsmccbiop.cpp:198
bool ProcessFile(DSMCCCacheModuleData *cachep, DSMCCCache *cache, unsigned char *data, unsigned long *curp)
Definition: dsmccbiop.cpp:266
DSMCCCacheKey m_objKey
Definition: dsmccbiop.h:186
unsigned int m_messageSize
Definition: dsmccbiop.h:185
std::vector< uint8_t > m_objInfo
Definition: dsmccbiop.h:187
unsigned char m_versionMinor
Definition: dsmccbiop.h:184
bool Process(DSMCCCacheModuleData *cachep, DSMCCCache *cache, unsigned char *data, unsigned long *curp)
Definition: dsmccbiop.cpp:96
unsigned char m_versionMajor
Definition: dsmccbiop.h:183
bool ProcessMsgHdr(const unsigned char *data, unsigned long *curp)
Definition: dsmccbiop.cpp:133
std::string m_objKind
Definition: dsmccbiop.h:190
ModuleDescriptorData m_descriptorData
Definition: dsmccbiop.h:216
unsigned char m_tapsCount
Definition: dsmccbiop.h:213
unsigned long m_minBlockTime
Definition: dsmccbiop.h:212
unsigned long m_blockTimeout
Definition: dsmccbiop.h:211
BiopTap m_tap
Definition: dsmccbiop.h:214
int Process(const unsigned char *Data)
Definition: dsmccbiop.cpp:334
unsigned long m_modTimeout
Definition: dsmccbiop.h:210
std::string m_kind
Definition: dsmccbiop.h:28
std::string m_id
Definition: dsmccbiop.h:27
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:16
BiopNameComp * m_comps
Definition: dsmccbiop.h:40
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:43
unsigned char m_compCount
Definition: dsmccbiop.h:39
unsigned long m_componentTag
Definition: dsmccbiop.h:78
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:429
char m_versionMajor
Definition: dsmccbiop.h:80
char m_componentDataLen
Definition: dsmccbiop.h:79
DSMCCCacheReference m_reference
Definition: dsmccbiop.h:82
char m_versionMinor
Definition: dsmccbiop.h:81
unsigned short m_id
Definition: dsmccbiop.h:51
unsigned short m_use
Definition: dsmccbiop.h:52
std::vector< uint8_t > m_selector
Definition: dsmccbiop.h:55
int Process(const unsigned char *data)
Definition: dsmccbiop.cpp:368
unsigned short m_assocTag
Definition: dsmccbiop.h:54
DSMCCCacheModuleData contains information about a module and holds the blocks for a partly completed ...
unsigned short ModuleId(void) const
unsigned long CarouselId(void) const
unsigned short StreamId(void) const
unsigned short m_nStreamTag
Definition: dsmcccache.h:53
unsigned short m_nModuleId
Definition: dsmcccache.h:52
unsigned long m_nCarouselId
Definition: dsmcccache.h:51
DSMCCCacheKey m_key
Definition: dsmcccache.h:54
The object carousel is transmitted as a directed graph.
Definition: dsmcccache.h:87
static void AddDirInfo(DSMCCCacheDir *dir, const BiopBinding *pBB)
Definition: dsmcccache.cpp:215
static void AddFileInfo(DSMCCCacheDir *dir, const BiopBinding *pBB)
Definition: dsmcccache.cpp:199
DSMCCCacheDir * Srg(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:127
DSMCCCacheDir * Directory(const DSMCCCacheReference &ref)
Definition: dsmcccache.cpp:150
Dsmcc * m_dsmcc
Definition: dsmcccache.h:124
void CacheFileData(const DSMCCCacheReference &ref, const QByteArray &data)
Definition: dsmcccache.cpp:173
Definition: dsmcc.h:78
ObjCarousel * AddTap(unsigned short componentTag, unsigned carouselId)
Add a tap.
Definition: dsmcc.cpp:61
unsigned long m_originalSize
Definition: dsmccbiop.h:202
void Process(const unsigned char *data, int length)
Definition: dsmccbiop.cpp:304
BiopConnbinder m_dsmConn
Definition: dsmccbiop.h:110
BiopObjLocation m_objLoc
Definition: dsmccbiop.h:106
int Process(const unsigned char *data) override
Definition: dsmccbiop.cpp:471
char m_liteComponentsCount
Definition: dsmccbiop.h:105
unsigned long m_dataLen
Definition: dsmccbiop.h:103
int Process(const unsigned char *data) override
Definition: dsmccbiop.cpp:465
virtual DSMCCCacheReference * GetReference()=0
virtual int Process(const unsigned char *)=0
unsigned int uint
Definition: compat.h:60
static constexpr uint32_t COMBINE32(const uint8_t *data, int idx)
Definition: dsmcc.h:120
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39