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