MHEG5  18.9.0
MHEG5 Documentation
mh5fileorm.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  * Copyright © 2000 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this source code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
26 /*---includes for this file--------------------------------------------------*/
27 #include "mh5fileorm.h"
28 #include "mh5stream.h"
29 #include "mh5memory.h"
30 #include "mh5debug.h"
31 #include "mh5profile.h"
32 #include "mh5object.h"
33 #include "mh5queue.h"
34 #include "mh5gate.h"
35 #include "mh5misc.h"
36 #include "mh5control.h"
37 #include <string.h>
38 
39 #ifdef COMMON_INTERFACE
40 #include "ci_appmmi.h"
41 #endif
42 #include "glue_queue.h"
43 #include "glue_main.h"
44 #include "glue_timers.h"
45 
46 #ifndef CI_PLUS_ONLY
47  #include "glue_dsmcc.h"
48  #ifdef INCLUDE_DSM_FG
49  #include "mh5filegroup.h"
50  #endif
51 #endif
52 
53 #ifdef INCLUDE_IC
54 #include "http_interface.h"
55 #include "mh5hfs.h"
56 #include "mh5tls.h"
57 #include "mh5access.h"
58 #include "mh5hash.h"
59 #include "mh5sig.h"
60 #endif
61 
62 
63 #ifdef PRINT_DSM_FILES
64 #include "glue_memory.h"
65 #include "dvb_service.h"
66 #include "dsm_control.h"
67 void DBG_FilePrintf(const char *format, ...);
68 #endif
69 #ifdef SAVING_DSM_FILES
70 #include "glue_memory.h"
71 #include "dvb_service.h"
72 #include "dsm_control.h"
73 void DBG_SaveFile(unsigned int srv_ndx, unsigned int srv_id, unsigned int crsl_id,
74  char *name, unsigned char *data, unsigned int len);
75 #endif
76 
77 /*---constant definitions for this file--------------------------------------*/
78 
79 #define MAX_PATHNAME_LENGTH (1024)
80 
81 #ifndef MAX_CI_REQUESTS
82 #define MAX_CI_REQUESTS (1)
83 #endif
84 #define CI_ACK_TIMEOUT 9999 /* about 10 secs */
85 
86 #define MIN_HTTP_REPLY_BLOCK (128)
87 #define MAX_REDIRECTS (5)
88 
89 #ifndef CI_PLUS_ONLY
90 #define DsmAlloc AllocRequest
91 #else
92 #define DsmAlloc AllocNothing
93 #endif
94 
95 #ifdef COMMON_INTERFACE
96 #define CiAlloc AllocRequest
97 #else
98 #define CiAlloc AllocNothing
99 #endif
100 
101 #ifdef INCLUDE_IC
102 #define HttpAlloc AllocRequest
103 #define HybrAlloc AllocRequest
104 #else
105 #define HttpAlloc AllocNothing
106 #define HybrAlloc AllocNothing
107 #endif
108 
109 #ifdef INCLUDE_IC
110 #define DEFAULT_ORIGIN ORIGIN_HYBRID
111 #else
112 #ifndef CI_PLUS_ONLY
113 #define DEFAULT_ORIGIN ORIGIN_DSM
114 #else
115 #define DEFAULT_ORIGIN ORIGIN_CI
116 #endif
117 #endif
118 
119 #define IS_HTTP_REQUEST(r) ((r)->origin == ORIGIN_HTTP || (r)->origin == ORIGIN_HTTPS)
120 #define IS_HTTPS_REQUEST(r) ((r)->origin == ORIGIN_HTTPS)
121 #define IS_HYBRID_REQUSET(r) ((r)->origin == ORIGIN_HYBRID)
122 
123 #ifndef NDEBUG
124 #define CHECK_ORM_MAGIC
125 #endif
126 #ifdef CHECK_ORM_MAGIC
127  #define ORM_REQUEST_MAGIC 0xdeadbeef
128  #define ORM_REQUEST_BAD_MAGIC 0xfeedface
129  #define SET_ORM_MAGIC(r) (r)->magic = ORM_REQUEST_MAGIC
130  #define CLEAR_ORM_MAGIC(r) (r)->magic = ORM_REQUEST_BAD_MAGIC
131  #define VERIFY_ORM_MAGIC(r) assert((r)->magic == ORM_REQUEST_MAGIC)
132 #else
133  #define SET_ORM_MAGIC(r)
134  #define CLEAR_ORM_MAGIC(r)
135  #define VERIFY_ORM_MAGIC(r)
136 #endif
137 
138 #ifdef TRACING
139 
140 #define PRINT_ERROR(x) TPRINT(TERROR, x)
141 
142 #else
143 
144 #define PRINT_ERROR(x)
145 
146 #endif /*TRACING*/
147 
148 #define ORM_STATE_STRING(r) \
149  ((r)->state == ORM_STATE_START ? "ORM_STATE_START" : \
150  (r)->state == ORM_STATE_QUEUED ? "ORM_STATE_QUEUED" : \
151  (r)->state == ORM_STATE_WAIT_ACCESS ? "ORM_STATE_WAIT_ACCESS" : \
152  (r)->state == ORM_STATE_CHECK_ACCESS ? "ORM_STATE_WAIT_ACCESS" : \
153  (r)->state == ORM_STATE_HAS_ACCESS ? "ORM_STATE_HAS_ACCESS" : \
154  (r)->state == ORM_STATE_WAIT_CERT ? "ORM_STATE_WAIT_CERT" : \
155  (r)->state == ORM_STATE_HAS_CERT ? "ORM_STATE_HAS_CERT" : \
156  (r)->state == ORM_STATE_REQUESTED ? "ORM_STATE_REQUESTED" : \
157  (r)->state == ORM_STATE_WAIT_VERIFY ? "ORM_STATE_WAIT_VERIFY" : \
158  (r)->state == ORM_STATE_CHECK_VERIFY ? "ORM_STATE_CHECK_VERIFY" : \
159  (r)->state == ORM_STATE_SUCCEEDED ? "ORM_STATE_SUCCEEDED" : \
160  (r)->state == ORM_STATE_FAILED ? "ORM_STATE_FAILED" : \
161  (r)->state == ORM_STATE_ABORTED ? "ORM_STATE_ABORTED" : \
162  "UNKNOWN")
163 
164 #ifdef MHEG5LOG
165  #undef TRACING
166  #define TRACING 511
167 #endif
168 
169 
170 /*---local typedef structs for this file-------------------------------------*/
171 
172 /* Enumerated type to tell where the origin of a file is (i.e. the part before
173  * "://")
174  */
175 
176 /* Enumerated type to tell the state of a request */
177 typedef enum
178 {
192 } E_OrmState;
193 
194 /* Enumerated type to tell the type of a request */
195 typedef enum
196 {
200 } E_OrmType;
201 
202 /* Asynchronous CI message record structure. */
203 
205 {
206  void *userData;
213 
214 #ifdef INCLUDE_IC
215 /* HTTP/S reply */
216 typedef struct HttpReplyBuffer_struct
217 {
218  U32BIT allocated;
219  U32BIT used;
220  U8BIT *data;
221  BOOLEAN valid;
222 } HttpReplyBuffer;
223 #endif /*INCLUDE_IC*/
224 
225 /* Request structures */
226 
227 typedef struct sOrmRequest *P_OrmRequest;
228 
229 typedef struct sOrmFuncs
230 {
231  P_OrmRequest (*Alloc)(void);
232  void (*Action)(P_OrmRequest request);
233  void (*Clear)(P_OrmRequest request);
234 } S_OrmFuncs;
235 
236 /* GET request */
237 typedef struct sOrmGetRequest
238 {
242  P_OrmRequest child;
245 
246 /* HTTP POST request */
247 typedef struct sOrmPostRequest
248 {
254 
255 typedef struct sOrmRequest
256 {
257  P_OrmRequest next;
258 #ifdef CHECK_ORM_MAGIC
260 #endif
264  void *requestRef;
265  void *userData;
268 #ifdef INCLUDE_IC
269  /* HTTP/S */
270  U16BIT redirectCount;
271  U32BIT certCount;
272  /* Hybrid */
273  void *hybrid_mapping;
274  MHEG5MappingIter_t hybrid_iter;
275 #endif
276  union
277  {
280  } r;
281 } S_OrmRequest;
282 
283 /*---local (static) variable declarations for this file----------------------*/
284 static S_OrmRequest *requestListHead = 0;
285 
286 /* dvb:// or rec:// resolution request */
287 static S_DVB_LOCATOR dvbMultiplexReference = {0, 0, 0};
288 
289 #ifdef COMMON_INTERFACE
290 /* CI:// requests */
291 static CiMessageContext *ciMessageListHead = 0;
292 static BOOLEAN ciMessageSent = FALSE;
293 static U16BIT ciRequestCount = 0;
294 static H_Timer ciAckTimerHandle = NULL;
295 #endif /*COMMON_INTERFACE*/
296 
297 static U32BIT globalRequestId = 0;
298 
299 /* Request list re-processing information */
300 static BOOLEAN inprocess = FALSE;
301 static BOOLEAN reprocess = FALSE;
302 
303 /* Reset information */
304 static BOOLEAN inreset = FALSE;
305 static MHEG5FileOrmResetMode currentResetMode = MHEG5_FILE_ORM_RESET_ALL;
306 
307 /*---local function prototypes for this file---------------------------------*/
308 
309 #ifdef INCLUDE_IC
310 static void HybridGetCallback( void *userData, S_CONTENT *ocontent );
311 static void HybridGetFailCallback( void *userData );
312 static BOOLEAN HttpGetCallback( void *userdata, U32BIT requestId,
313  HttpResponse_t *response);
314 static BOOLEAN HttpPostCallback(void *userdata, U32BIT requestId,
315  HttpResponse_t *response);
316 #endif /* INCLUDE_IC */
317 
318 #ifndef CI_PLUS_ONLY
319 /* DSM-CC Get request */
320 static void DsmAction(S_OrmRequest *ormRequest);
321 static void DsmClear(S_OrmRequest *ormRequest);
322 #else
323 #define DsmAction DummyFunc
324 #define DsmClear DummyFunc
325 #endif /* !CI_PLUS_ONLY */
326 
327 /* CI Get request */
328 #ifdef COMMON_INTERFACE
329 static BOOLEAN CiSetFileContent(U8BIT *data, U32BIT size, S_CONTENT *pContent);
330 static void CiAction(S_OrmRequest *ormRequest);
331 static void CiClear(S_OrmRequest *ormRequest);
332 #else
333 #define CiAction DummyFunc
334 #define CiClear DummyFunc
335 #endif /*COMMON_INTERFACE*/
336 
337 /* DVB or REC Get request */
338 static void DvbAction(S_OrmRequest *ormRequest);
339 static void DvbClear(S_OrmRequest *ormRequest);
340 static P_OrmRequest DvbAlloc(void);
341 
342 #if defined(CI_PLUS_ONLY) || !defined(COMMON_INTERFACE) || !defined(INCLUDE_IC)
343 static P_OrmRequest AllocNothing(void);
344 #endif
345 static P_OrmRequest AllocRequest(void);
346 
347 #if !defined(CI_PLUS_ONLY) || defined(INCLUDE_IC)
348 static S_OrmRequest* FindRequest(U32BIT requestId);
349 #endif
350 
351 #ifdef INCLUDE_IC
352 
353 static void HybrAction(S_OrmRequest *ormRequest);
354 static void HybrClear(S_OrmRequest *ormRequest);
355 static void HttpAction(S_OrmRequest *ormRequest);
356 static void HttpClear(S_OrmRequest *ormRequest);
357 
358 /* HTTP POST request */
359 static MHEG5Bool PostProcess(S_OrmRequest *ormRequest);
360 
361 static void CheckServerAccess(S_OrmRequest *ormRequest);
362 static void CheckTlsCertificates(S_OrmRequest *ormRequest);
363 static void PerformHttpRequest(S_OrmRequest *ormRequest);
364 static void VerifyRequestContent(S_OrmRequest *ormRequest);
365 
366 static void HttpRedirect(S_OrmRequest *ormRequest);
367 
368 /* Callbacks for sub-systems */
369 static void TlsCertCallback(void);
370 static void ServerAccessCallback(void);
371 static void VerificationCallback(void);
372 
373 static void AppendData(HttpReplyBuffer *hcontent, U8BIT *data, U32BIT dataLen);
374 
375 #else /* !INCLUDE_IC */
376 
377 #define HybrAction DummyFunc
378 #define HybrClear DummyFunc
379 #define HttpAction DummyFunc
380 #define HttpClear DummyFunc
381 
382 #endif /* INCLUDE_IC */
383 
384 static MHEG5Bool DefaultGetProcess(S_OrmRequest *ormRequest);
385 
386 static void ReprocessRequestList(void);
387 static void ProcessRequestList(void);
388 
389 #if defined(CI_PLUS_ONLY) || !defined(COMMON_INTERFACE) || !defined(INCLUDE_IC)
390 static void DummyFunc(S_OrmRequest *ormRequest) {}
391 #endif
392 
393 /*---local (static) variable declarations for this file----------------------*/
394 
395 static S_OrmFuncs ormFunctions[ORIGIN_MAX] = {
396  /*DSM */ { DsmAlloc, DsmAction, DsmClear },
397  /*CI */ { CiAlloc, CiAction, CiClear },
398  /*HYBRID */ { HybrAlloc, HybrAction, HybrClear },
399  /*HTTP */ { HttpAlloc, HttpAction, HttpClear },
400  /*HTTPS */ { HttpAlloc, HttpAction, HttpClear },
401  /*DVB */ { DvbAlloc, DvbAction, DvbClear },
402  /*REC */ { DvbAlloc, DvbAction, DvbClear },
403 };
404 
405 /*---local function definitions----------------------------------------------*/
406 
407 #if defined(CI_PLUS_ONLY) || !defined(COMMON_INTERFACE) || !defined(INCLUDE_IC)
408 static P_OrmRequest AllocNothing(void)
409 {
410  return NULL;
411 }
412 #endif
413 
414 static P_OrmRequest AllocRequest(void)
415 {
416  P_OrmRequest request;
417  request = MHEG5getMem(sizeof(S_OrmRequest));
418  if (request != NULL)
419  {
420  memset(request, 0, sizeof(S_OrmRequest));
421  SET_ORM_MAGIC(request);
422  }
423  return request;
424 }
425 
426 static P_OrmRequest DvbAlloc(void)
427 {
428  static S_OrmRequest dvbRequest;
429  S_OrmRequest *request = &dvbRequest;
430  memset(request, 0, sizeof(S_OrmRequest));
431  SET_ORM_MAGIC(request);
432  return request;
433 }
434 
435 #ifdef INCLUDE_IC
436 
440 static void DefaultDataClear( void *data )
441 {
442  MHEG5freeMem(data);
443 }
444 
445 #endif /* INCLUDE_IC */
446 
447 
448 #ifdef COMMON_INTERFACE
449 
454 static void AddToCiMessageContextList(CiMessageContext *contextToAdd)
455 {
456  /* Add context to the head of the list */
457  contextToAdd->next = ciMessageListHead;
458  ciMessageListHead = contextToAdd;
459 
460  DEBUG_PRINT(("Added message context to head of ciMessageListHead list\n"));
461 }
462 
469 static void RemoveFromCiMessageContextList(CiMessageContext *contextToRemove)
470 {
471  if (contextToRemove == ciMessageListHead)
472  {
473  /* Context to remove is at the head of the list - remove it by changing
474  * the list head pointer
475  */
476  ciMessageListHead = ciMessageListHead->next;
477 
478  INFO_PRINT(("Removed message context from head of ciMessageListHead list\n"));
479  }
480  else
481  {
482  CiMessageContext *context;
483 
484  /* Search the context list, looking for a pointer to this context */
485  context = ciMessageListHead;
486 
487  while (context->next)
488  {
489  if (context->next == contextToRemove)
490  {
491  /* Found the context to remove in the list - route list pointers
492  * round it.
493  */
494  context->next = contextToRemove->next;
495  INFO_PRINT(("Removed message context from middle or end of ciMessageListHead list\n"));
496  return; /*** RETURN ***/
497  }
498  context = context->next;
499  }
500 
501  /* We did not find the specified context - print an error message */
502  ERROR_PRINT(("INTERNAL ERROR: RemoveFromCiMessageContextList - context not found\n"));
503  assert(0);
504  }
505 }
506 #endif /*COMMON_INTERFACE*/
507 
513 static void AddToRequestList(S_OrmRequest *request)
514 {
515  S_OrmRequest **pRequest;
516 
517  pRequest = &requestListHead;
518  while (*pRequest != NULL)
519  {
520  pRequest = &(*pRequest)->next;
521  }
522  *pRequest = request;
523 }
524 
531 static void RemoveFromRequestList(S_OrmRequest *request)
532 {
533  S_OrmRequest **pRequest;
534 
535  assert(request != NULL);
536 
537  pRequest = &requestListHead;
538  while (*pRequest != NULL && *pRequest != request)
539  {
540  pRequest = &(*pRequest)->next;
541  }
542 
543  if (*pRequest == request)
544  {
545  *pRequest = request->next;
546  }
547  else
548  {
549  /* We did not find the specified request - print an error message */
550  ERROR_PRINT(("INTERNAL ERROR: RemoveFromRequestList - request not found\n"));
551  assert(0);
552  }
553 }
554 
555 #ifdef COMMON_INTERFACE
556 static void ciAckTimeoutFunc( BOOLEAN trig, void *cRef, H_Timer timer )
557 {
558  if (trig == TRUE)
559  {
560  TRACE(TERROR, ("CAM never returned an ACK! ciRequestCount=%d", ciRequestCount))
561  if (ciRequestCount != 0)
562  {
563  ciRequestCount = 0;
564  ciMessageSent = FALSE;
565  }
566  }
567 }
568 #endif /*COMMON_INTERFACE*/
569 
570 /*---global function definitions---------------------------------------------*/
571 
577 {
578 #ifdef INCLUDE_IC
579  MHEG5AddTlsCertificateCallback(TlsCertCallback);
580  MHEG5AddServerAccessCallback(ServerAccessCallback);
581  MHEG5SetVerificationCallback(VerificationCallback);
582 #endif
583 }
584 
596 {
597  S_OrmRequest *ormRequest;
598  MHEG5Bool requestDone;
599  BOOLEAN remove;
600 
601  inreset = TRUE;
602  currentResetMode = resetMode;
603 
604  ormRequest = requestListHead;
605  while (ormRequest)
606  {
607  if (resetMode == MHEG5_FILE_ORM_RESET_ALL)
608  {
609  remove = TRUE;
610  }
611  else if (ormRequest->type == ORM_TYPE_GET)
612  {
613  if (ormRequest->r.get.priority & FRP_SERVER)
614  {
615  /* don't clear 'external' requests such as TLS or server access */
616  remove = FALSE;
617  }
618  else if ((resetMode == MHEG5_FILE_ORM_RESET_SCENE_OBJECTS) &&
619  (ormRequest->r.get.priority & FRP_IN_APP))
620  {
621  /* don't clear requests for application ingredients */
622  remove = FALSE;
623  }
624  else
625  {
626  /* all group and ingredients can be removed */
627  remove = TRUE;
628  }
629  }
630  else
631  {
632  /*
633  * remove is unitialised here so set to FALSE?
634  * otherwise the subsequent check on remove will have unexpected results.
635  */
636  remove = FALSE;
637  }
638 
639  if (remove)
640  {
641  /* Notify load failure */
642  ormRequest->state = ORM_STATE_FAILED;
643  requestDone =
644  #ifdef INCLUDE_IC
645  (ormRequest->type == ORM_TYPE_POST)? PostProcess(ormRequest) :
646  #endif
647  DefaultGetProcess(ormRequest);
648 
649  assert(requestDone);
650  if (requestDone)
651  {
652  /* Free off memory for the item we just removed */
653  ormFunctions[ormRequest->origin].Clear(ormRequest);
654  }
655 
656  /* Start from beginning of list, in case callback changed anything */
657  ormRequest = requestListHead;
658  }
659  else
660  {
661  ormRequest = ormRequest->next;
662  }
663  }
664 
665 #ifdef COMMON_INTERFACE
666  /* Free off all entries in the message list */
667  while (ciMessageListHead)
668  {
669  CiMessageContext *ciItem;
670 
671  /* Remember the current list head */
672  ciItem = ciMessageListHead;
673 
674  /* Remove the current list head from the list */
675  RemoveFromCiMessageContextList(ciItem);
676 
677  /* Free off memory for the item we just removed */
678  MHEG5stringDestruct(&ciItem->input);
679  if (ciItem->output.data != NULL)
680  {
681  MHEG5CiAckData(ciItem->output.data);
682  }
683  MHEG5freeMem(ciItem);
684  }
685 
686  if (ciRequestCount != 0)
687  {
688  if (ciAckTimerHandle != NULL)
689  {
690  VT_TimerDestroy( ciAckTimerHandle );
691  ciAckTimerHandle = NULL;
692  }
693  (void)VT_TimerCreate( CI_ACK_TIMEOUT, (F_TimerCallback)ciAckTimeoutFunc, 0, &ciAckTimerHandle );
694  }
695 #endif /*COMMON_INTERFACE*/
696 
697  inreset = FALSE;
698 }
699 
713 {
714  if (inreset)
715  {
716  if (resetMode != NULL)
717  {
718  *resetMode = currentResetMode;
719  }
720  return TRUE;
721  }
722  return FALSE;
723 }
724 
725 #if defined(PRINT_DSM_FILES) || defined(SAVING_DSM_FILES)
726 
727 #define PRNT_FL_MAX 37
728 typedef struct sFileNames
729 {
730  struct sFileNames *next;
731  int nmlen;
732  U8BIT name[4];
733 } FileNames_t;
734 
735 typedef struct sPrintFiles
736 {
737  struct sPrintFiles *next;
738  MHEG5Int srv_ndx;
739  FileNames_t *file_head;
740 } PrintFiles_t;
741 
742 PrintFiles_t print_files_hash[PRNT_FL_MAX];
743 int print_files = 0;
744 int file_printing = 1;
745 
746 void dumpDsmFile( U8BIT *fname, U8BIT *data, U32BIT size )
747 {
748  const char digits[16] = "0123456789ABCDEF";
749  S_DVB_LOCATOR multiplexRef;
750  S_DVB_LOCATOR dvbLocator;
751  S32BIT service_ndx;
752  PrintFiles_t *p_pf;
753  FileNames_t *p_fn;
754  int nlen;
755 
756  if (!file_printing)
757  return;
758 
759  MHEG5streamGetCurrentService(&multiplexRef);
760 
761  dvbLocator.original_network_id = multiplexRef.original_network_id;
762  dvbLocator.transport_stream_id = multiplexRef.transport_stream_id;
763  dvbLocator.service_id = (U16BIT)multiplexRef.service_id;
764  /* Get the service index from the controlling environment */
765  if (DVB_MhegDvbLocatorToIndex(&dvbLocator, &service_ndx) != MHERR_OK || service_ndx == -1)
766  return;
767  nlen = strlen(fname);
768  if (print_files == 0)
769  {
770  /* initialise */
771  memset( print_files_hash, 0, 37 * sizeof(PrintFiles_t));
772  }
773  p_pf = &print_files_hash[service_ndx % PRNT_FL_MAX];
774 
775  while ((p_pf->next) && (p_pf->srv_ndx != service_ndx))
776  p_pf = p_pf->next;
777 
778  if (p_pf->srv_ndx != service_ndx)
779  {
780  p_pf->srv_ndx = service_ndx;
781  }
782  p_fn = p_pf->file_head;
783  while (p_fn)
784  {
785  if ((nlen == p_fn->nmlen) &&
786  (memcmp( p_fn->name, fname, nlen ) == 0))
787  {
788  break;
789  }
790  p_fn = p_fn->next;
791  }
792  if (p_fn == 0)
793  {
794  /* not a duplicate - now save details of this file */
795  p_fn = p_pf->file_head;
796  p_pf->file_head = (FileNames_t *)STB_MemAlloc(sizeof(FileNames_t) + nlen - 2);
797  p_pf->file_head->next = p_fn;
798  p_pf->file_head->nmlen = nlen;
799  memcpy( p_pf->file_head->name, fname, nlen );
800 
801  #ifdef SAVING_DSM_FILES
802  DBG_SaveFile(service_ndx, dvbLocator.service_id, DSMCC_CurrentCarouselId(MHEG5_DsmccInstance()), (char *)fname, data, size);
803  #endif
804  #ifdef PRINT_DSM_FILES
805  DBG_FilePrintf( "%ld_%d/%s", (long int)service_ndx, dvbLocator.service_id, (char *)fname );
806  for (nlen = 0; nlen != size; nlen++)
807  {
808  if ((nlen & 0x1f) == 0x00)
809  DBG_FilePrintf("\n");
810  DBG_FilePrintf("%c%c", digits[data[nlen] >> 4], digits[data[nlen] & 0xf]);
811  }
812  DBG_FilePrintf("\n*\n");
813  #endif
814  print_files++;
815  }
816 }
817 
818 #define PRINTFILE(t, n, d, s) /*if (t == ORM_TYPE_GET)*/ dumpDsmFile(n, d, s)
819 #else
820 #define PRINTFILE(t, n, d, s)
821 #endif
822 
831 {
832 #ifdef COMMON_INTERFACE
833  CiMessageContext *ciItem;
835 #endif
836 
837  reprocess = FALSE;
838  inprocess = TRUE;
839 
840  ProcessRequestList();
841 
842 #ifdef COMMON_INTERFACE
843  ciItem = ciMessageListHead;
844  while (ciItem != NULL)
845  {
846  switch (ciItem->successFlag)
847  {
848  default:
849  /* Remove the item from the list */
850  RemoveFromCiMessageContextList(ciItem);
851 
852  /* Send the reply to the callback */
853  output.data = &ciItem->output.data[1];
854  output.len = ciItem->output.len - 1;
855  (ciItem->callback)(ciItem->userData, output, MHEG5TRUE);
856 
857  if (ciItem->output.data != NULL)
858  {
859  MHEG5CiAckData(ciItem->output.data);
860  }
861  MHEG5freeMem(ciItem);
862 
863  /* The callback may have removed or added entries into the context
864  * list, therefore we cannot rely on any previously held information
865  * about the next entry in the list. We must start again from the
866  * list head.
867  */
868  ciItem = ciMessageListHead;
869  break;
870 
871  case FS_STATUS_INVALID:
872  /* File hasn't been requested yet */
873  if (ciRequestCount < MAX_CI_REQUESTS && !ciMessageSent)
874  {
875  /* Request the file from the CI module */
876  if (ciItem->input.data != NULL &&
877  STB_CIFileRequest(MHEG5GetCiModuleId(), ciItem->input.data, ciItem->input.len) == TRUE)
878  {
879  /* File has been requested */
880  ciItem->successFlag = FS_STATUS_PENDING;
881  ciRequestCount++;
882  ciMessageSent = TRUE;
883 
884  /* We can finally get rid of the message */
885  MHEG5stringDestruct(&ciItem->input);
886 
887  /* Move on to next item */
888  ciItem = ciItem->next;
889  }
890  else
891  {
892  ERROR_PRINT(("MHEG5FileOrmProcess : error from ciFileRequest\n"));
893 
894  /* Pass error back via callback */
895  (ciItem->callback)(ciItem->userData, ciItem->output, MHEG5FALSE);
896 
897  /* Remove the item from the list */
898  RemoveFromCiMessageContextList(ciItem);
899  MHEG5stringDestruct(&ciItem->input);
900  MHEG5freeMem(ciItem);
901 
902  /* Start from the beginning */
903  ciItem = ciMessageListHead;
904  }
905  break;
906  } /* else Can't do much about this one, so fall through to 'pending' case */
907  case FS_STATUS_PENDING:
908  ciItem = ciItem->next;
909  break;
910  }
911  }
912 #endif /*COMMON_INTERFACE*/
913 
914  inprocess = FALSE;
915  return reprocess;
916 }
917 
928 static U8BIT* buildName(MHEG5String name, MHEG5String *url, E_FS_ORIGIN *origin)
929 {
930  U8BIT *data;
931  int len;
932 
933  assert(origin);
934 
935  /* Set default to an empty string */
936  *origin = ORIGIN_ERROR;
937 
938  /* Check for special service names */
939  if ((name.len > 6) && (MHEG5strncmp(name.data, "dvb://", 6) == 0))
940  {
941  *origin = ORIGIN_DVB;
942  }
943  else if ((name.len > 6) && (MHEG5strncmp(name.data, "rec://", 6) == 0))
944  {
945  *origin = ORIGIN_REC;
946  }
947 
948  if ((*origin == ORIGIN_DVB) || (*origin == ORIGIN_REC))
949  {
950  /* Make a copy of the input name into the output buffer */
951  *url = MHEG5stringCopy( name );
952  data = url->data;
953  }
954  else
955  {
956  /* Convert using name mapping rules */
957  *url = MHEG5convertGIDGetOrigin(&name,origin);
958  len = url->len;
959  data = url->data;
960  if (len == 0)
961  {
962  WARNING_PRINT(("buildName illegal name \"%s\"\n", name.data));
963  *origin = ORIGIN_ERROR;
964  }
965  else
966  {
967  DEBUG_PRINT(("buildName [%.*s] %s, %d\n", name.len, name.data, data, *origin));
968  data += MHEG5FullOriginLength(*origin);
969  }
970  }
971  return data;
972 }
973 
979 void MHEG5FileOrmClear( void *orm_ref )
980 {
981  S_OrmRequest *ormRequest, *next;
982 
983  /* Start at the list head */
984  ormRequest = requestListHead;
985 
986  while (ormRequest != NULL)
987  {
988  /* Keep a pointer to the next item in the list */
989  next = ormRequest->next;
990 
991  /* Check for matching object reference */
992  if (ormRequest == orm_ref && ormRequest->type == ORM_TYPE_GET)
993  {
994  /* Remove this entry from the request list */
995  RemoveFromRequestList(ormRequest);
996 
997  /* Destroy the entry */
998  ormRequest->state = ORM_STATE_ABORTED;
999  ormFunctions[ormRequest->origin].Clear(ormRequest);
1000 
1001  next = requestListHead;
1002  }
1003  ormRequest = next;
1004  }
1005 }
1006 
1013 static MHEG5Bool MHEG5FileOrmIsWaiting(void *usr, MHEG5String url)
1014 {
1015  S_OrmRequest *ormRequest, *next;
1016  BOOLEAN check;
1017 
1018  /* Start at the list head */
1019  ormRequest = requestListHead;
1020 
1021  while (ormRequest)
1022  {
1023  /* Keep a pointer to the next item in the list */
1024  next = ormRequest->next;
1025 
1026  /* Check for matching object reference */
1027  check = ormRequest->type == ORM_TYPE_GET && ormRequest->userData == usr;
1028  #ifdef INCLUDE_IC
1029  if (check)
1030  {
1031  /* For IC we also need to check "special" requests such as hash
1032  * and signature files.
1033  */
1034  check = check && !(ormRequest->r.get.priority & FRP_HASH);
1035  }
1036  #endif
1037  if (check)
1038  {
1039  if (ormRequest->url.len == url.len &&
1040  strcmp((char *)ormRequest->url.data, (char *)url.data) == 0)
1041  {
1042  return MHEG5TRUE;
1043  }
1044  else
1045  {
1046  /* matching object but requesting new name */
1047 
1048  /* Remove this entry from the file orm context list */
1049  RemoveFromRequestList(ormRequest);
1050 
1051  /* Destroy the entry */
1052  ormFunctions[ormRequest->origin].Clear(ormRequest);
1053  return MHEG5FALSE;
1054  }
1055  }
1056  ormRequest = next;
1057  }
1058  return MHEG5FALSE;
1059 }
1060 
1061 #ifdef INCLUDE_DSM_FG
1062 static void FileGroupComplete( E_FsStatus status, S_CONTENT *content )
1063 {
1064  S_OrmRequest *ormRequest;
1065  U32BIT requestId;
1066  requestId = (U32BIT)content->user_data;
1067  ormRequest = requestListHead;
1068  while (ormRequest != NULL)
1069  {
1070  if (ormRequest->requestId == requestId)
1071  {
1072  switch (status)
1073  {
1074  case FS_STATUS_OK:
1075  TRACE(TFILE, (" Got size=%d, for:%s", content->size, ormRequest->url.data));
1076  ormRequest->state = ORM_STATE_SUCCEEDED;
1077  //ormRequest->r.get.ocontent = *content;
1078  break;
1079 
1080  case FS_STATUS_INVALID:
1081  ormRequest->state = ORM_STATE_QUEUED;
1082  break;
1083 
1084  case FS_STATUS_ERROR:
1085  TRACE(TFILE, (" Failed to get %s", ormRequest->url.data));
1086  ormRequest->state = ORM_STATE_FAILED;
1087  break;
1088 
1089  case FS_STATUS_ABORT:
1090  TRACE(TFILE, (" ABORTED %s", ormRequest->url.data));
1091  if (ormRequest->state == ORM_STATE_REQUESTED)
1092  {
1093  ormRequest->state = ORM_STATE_FAILED;
1094  }
1095  /* else it should already be aborted state */
1096  break;
1097 
1098  case FS_STATUS_PENDING:
1099  TRACE(TERROR, (" STILL PENDING! %s", ormRequest->url.data))
1100  ormRequest->state = ORM_STATE_REQUESTED;
1101  break;
1102 
1103  default:
1104  /* An error ocurred */
1105  TRACE(TERROR, ("UNKNOWN return %d for %s", status, ormRequest->url.data))
1106  ormRequest->state = ORM_STATE_FAILED;
1107  }
1109  break;
1110  }
1111  ormRequest = ormRequest->next;
1112  }
1113 }
1114 
1115 static MHEG5Bool FileGroupAction( E_FS_ORIGIN origin, U8BIT *path, P_OrmRequest ormRequest, U16BIT priority )
1116 {
1117  E_FsStatus status;
1118  MHEG5Bool done;
1119  /* not zero cache priority */
1120  if (priority & FRP_EXISTS)
1121  {
1122  status = FG_FileExists( origin, (char *)path );
1123  }
1124  else
1125  {
1126  status = FG_LoadRequest( origin, (char *)path, FileGroupComplete,
1127  &ormRequest->r.get.ocontent, (U8BIT)(priority & FRP_CACHE_MASK) );
1128  }
1129  switch (status)
1130  {
1131  case FS_STATUS_OK:
1132  {
1133  ormRequest->state = ORM_STATE_SUCCEEDED;
1134  ReprocessRequestList();
1135  done = MHEG5TRUE;
1136  break;
1137  }
1138  case FS_STATUS_PENDING:
1139  {
1140  TRACE(TFILE, (" loading %s", ormRequest->url.data));
1141  ormRequest->state = ORM_STATE_REQUESTED;
1142  ReprocessRequestList();
1143  done = MHEG5TRUE;
1144  break;
1145  }
1146  case FS_STATUS_INVALID:
1147  {
1148  done = MHEG5FALSE;
1149  break;
1150  }
1151  default:
1152  case FS_STATUS_ERROR:
1153  {
1154  TRACE(TFILE, ("(%s) stat %d", ormRequest->url.data, status));
1155  ormRequest->state = ORM_STATE_FAILED;
1156  ReprocessRequestList();
1157  done = MHEG5TRUE;
1158  }
1159  }
1160  return done;
1161 }
1162 #endif /*INCLUDE_DSM_FG*/
1163 
1179 void* MHEG5FileOrmGet( MHEG5String name, U16BIT priority, void *userData,
1180  F_CB_Good cbGood, F_CB_Fail cbFail)
1181 {
1182  MHEG5String url;
1183 #if defined(INCLUDE_DSM_FG) || defined(TRACING)
1184  U8BIT *path;
1185 #endif
1186  E_FS_ORIGIN origin = DEFAULT_ORIGIN;
1187  P_OrmRequest ormRequest;
1188  MHEG5Bool requestDone;
1189 
1190  assert( cbGood != NULL );
1191  assert( cbFail != NULL );
1192 
1193  /* Check that name is valid */
1194  if (!name.len)
1195  {
1196  /* Specified file name is empty - indicate that it does not exist */
1197  cbFail( userData );
1198  ormRequest = NULL;
1199  }
1200  else
1201  {
1202  /* Build absolute file name */
1203  #if defined(INCLUDE_DSM_FG) || defined(TRACING)
1204  path =
1205  #endif
1206  buildName(name, &url, &origin);
1207  if (origin == ORIGIN_ERROR)
1208  {
1209  /* Specified file name is invalid - indicate that it does not exist */
1210  cbFail( userData );
1211  MHEG5stringDestruct( &url );
1212  ormRequest = NULL;
1213  }
1214  /* Check any outstanding requests for this object */
1215  else if ((userData != NULL) && (MHEG5FileOrmIsWaiting(userData, url)))
1216  {
1217  TRACE(TFILE, ("repeated request (%p) for file %s", userData, url.data));
1218  MHEG5stringDestruct( &url );
1219  ormRequest = NULL;
1220  }
1221  else
1222  {
1223 
1224  ormRequest = ormFunctions[origin].Alloc();
1225  if (ormRequest == NULL)
1226  {
1227  TRACE(TERROR, ("memory failure, or origin not supported; url=%s", path))
1228  cbFail( userData );
1229  MHEG5stringDestruct( &url );
1230  ormRequest = NULL;
1231  }
1232  else
1233  {
1234  U_PARAM ud;
1235  ormRequest->url = url;
1236  ormRequest->origin = origin;
1237  ormRequest->userData = userData;
1238  ormRequest->r.get.cbGood = cbGood;
1239  ormRequest->r.get.cbFail = cbFail;
1240  ormRequest->requestId = ++globalRequestId;
1241  ud.u32 = globalRequestId;
1242  ormRequest->r.get.ocontent.user_data = ud.ptr;
1243  if (origin == ORIGIN_HTTP || origin == ORIGIN_HTTPS)
1244  {
1245  priority |= FRP_VERIFY;
1246  }
1247  ormRequest->r.get.priority = priority;
1248  TRACE(TFILE, ("Ptr=%p url=%s priority=0x%x", ormRequest, path, priority))
1249 
1250  /* Add request to list */
1251  AddToRequestList(ormRequest);
1252  #ifdef INCLUDE_DSM_FG
1253  if (!FileGroupAction(origin,path,ormRequest,priority))
1254  #endif
1255  {
1256  ormFunctions[origin].Action(ormRequest);
1257  }
1258  VERIFY_ORM_MAGIC(ormRequest);
1259  if (ormRequest->state == ORM_STATE_SUCCEEDED ||
1260  ormRequest->state == ORM_STATE_FAILED)
1261  {
1262  requestDone = DefaultGetProcess(ormRequest);
1263  if (requestDone)
1264  {
1265  ormFunctions[origin].Clear(ormRequest);
1266  ormRequest = NULL;
1267  }
1268  }
1269  }
1270  }
1271  }
1272  return ormRequest;
1273 }
1274 
1290 void* MHEG5FileOrmRetrieve( E_FS_ORIGIN origin, S_STRING location, S_STRING name,
1291  U16BIT priority, void *userData, F_CB_Good cbGood, F_CB_Fail cbFail)
1292 {
1293  MHEG5String url;
1294  P_OrmRequest ormRequest;
1295  MHEG5Bool requestDone;
1296 
1297  assert( cbGood != NULL );
1298  assert( cbFail != NULL );
1299  assert( name.zlen );
1300 
1301  if (origin == ORIGIN_ERROR)
1302  {
1303  /* Specified file name is invalid - indicate that it does not exist */
1304  cbFail( userData );
1305  ormRequest = NULL;
1306  }
1307  else
1308  {
1309  url = MHEG5CreateUrl(origin,location,name);
1310  if (url.data == NULL)
1311  {
1312  cbFail( userData );
1313  ormRequest = NULL;
1314  }
1315  else
1316  {
1317  ormRequest = ormFunctions[origin].Alloc();
1318  if (ormRequest == NULL)
1319  {
1320  TRACE(TERROR, ("memory failure, or origin not supported; url=%s", url.data))
1321  cbFail( userData );
1322  MHEG5stringDestruct( &url );
1323  ormRequest = NULL;
1324  }
1325  else
1326  {
1327  U_PARAM ud;
1328  ormRequest->url = url;
1329  ormRequest->origin = origin;
1330  ormRequest->type = ORM_TYPE_FGR;
1331  ormRequest->userData = userData;
1332  ormRequest->r.get.cbGood = cbGood;
1333  ormRequest->r.get.cbFail = cbFail;
1334  ormRequest->requestId = ++globalRequestId;
1335  ud.u32 = globalRequestId;
1336  ormRequest->r.get.ocontent.user_data = ud.ptr;
1337  if (origin == ORIGIN_HTTP || origin == ORIGIN_HTTPS)
1338  {
1339  priority |= FRP_VERIFY;
1340  }
1341  ormRequest->r.get.priority = priority;
1342  TRACE(TFILE, ("Ptr=%p url=%s", ormRequest, url.data))
1343 
1344  /* Add request to list */
1345  AddToRequestList(ormRequest);
1346  ormFunctions[origin].Action(ormRequest);
1347  VERIFY_ORM_MAGIC(ormRequest);
1348  if (ormRequest->state == ORM_STATE_SUCCEEDED ||
1349  ormRequest->state == ORM_STATE_FAILED)
1350  {
1351  requestDone = DefaultGetProcess(ormRequest);
1352  if (requestDone)
1353  {
1354  ormFunctions[origin].Clear(ormRequest);
1355  ormRequest = NULL;
1356  }
1357  }
1358  }
1359  }
1360  }
1361  return ormRequest;
1362 }
1363 
1364 #ifdef COMMON_INTERFACE
1365 
1375 MHEG5Bool MHEG5FileOrmSendCiMessage(MHEG5String input, F_CB_CiMsg callback, void *userData)
1376 {
1377  U8BIT *data;
1378  CiMessageContext *w;
1379  S32BIT retval;
1380  MHEG5Bool err = MHEG5TRUE;
1381 
1382  DEBUG_PRINT(("INFO: MHEG5FileOrmSendCiMessage ( %.*s, 0x%x )\n", input.len, input.data));
1383 
1384  /* Create CI message context */
1385  w = (CiMessageContext *) MHEG5getMem( sizeof(CiMessageContext));
1386  if (!w)
1387  {
1388  ERROR_PRINT(("ERROR: MHEG5FileOrmSendCiMessage unable to allocate memory\n"));
1389  return MHEG5FALSE;
1390  }
1391 
1392  /* Clear newly allocated data to zero */
1393  memset(w, 0, sizeof(CiMessageContext));
1394 
1395  w->userData = userData;
1397  w->callback = callback;
1398  w->output.data = NULL;
1399  w->output.len = 0;
1400 
1401  /* Create CI file request for message */
1402  data = (U8BIT *) STR_DataAlloc( input.len + 1 );
1403  if (data)
1404  {
1405  /* Create CI file request for message */
1406  data[0] = 0x01; /* 'data' */
1407  memcpy(&data[1], input.data, input.len);
1408 
1409  /* Add message to list of CI messages */
1410  AddToCiMessageContextList(w);
1411 
1412  if (ciRequestCount < MAX_CI_REQUESTS && !ciMessageSent)
1413  {
1414  /* Send the file request to CI module */
1415  retval = STB_CIFileRequest(MHEG5GetCiModuleId(), data, input.len + 1);
1416  if (retval == TRUE)
1417  {
1418  /* File has been requested */
1420  ciRequestCount++;
1421  ciMessageSent = TRUE;
1422 
1423  /* Can get rid of the data, it's been sent to the CI module */
1424  STR_DataFree(data, input.len + 1);
1425  }
1426  else
1427  {
1428  /* An error ocurred */
1429  ERROR_PRINT(("ERROR: MHEG5FileOrmSendCiMessage ciFileRequest retval is %d\n", retval));
1430 
1431  /* Remove entry from list of requested objects */
1432  RemoveFromCiMessageContextList(w);
1433  STR_DataFree(data, input.len + 1);
1434  MHEG5freeMem(w);
1435  err = MHEG5FALSE;
1436  }
1437  }
1438  else
1439  {
1440  /* Need to store the message until we're ready for file request */
1441  w->input.data = data;
1442  w->input.len = input.len + 1;
1443  }
1444  }
1445  else
1446  {
1447  /* Cannot create message, destroy context */
1448  ERROR_PRINT(("ERROR: MHEG5FileOrmSendCiMessage unable to allocate memory\n"));
1449  MHEG5freeMem(w);
1450  err = MHEG5FALSE;
1451  }
1452 
1453  return err;
1454 }
1455 
1456 #endif /*COMMON_INTERFACE*/
1457 
1458 
1459 #ifdef INCLUDE_IC
1460 
1472 MHEG5Bool MHEG5FileOrmReturnData(MHEG5String name, MHEG5String postData,
1473  F_CB_Post callback, void *userData)
1474 {
1475  MHEG5String invalid = {0, 0};
1476  MHEG5String url;
1477  E_FS_ORIGIN origin = ORIGIN_HYBRID;
1478  S_OrmRequest *ormRequest;
1479  MHEG5Bool success = MHEG5FALSE;
1480  MHEG5Bool requestDone;
1481 
1482  /* Check that URL is valid */
1483  if (!name.len)
1484  {
1485  /* Specified file name is empty */
1486  callback(userData, invalid, 0);
1487  }
1488  else
1489  {
1490  /* Build absolute file name */
1491  buildName(name, &url, &origin);
1492  if (origin == ORIGIN_ERROR)
1493  {
1494  /* Specified file name is invalid */
1495  callback(userData, invalid, 0);
1496  MHEG5stringDestruct( &url );
1497  }
1498  else
1499  {
1500  ormRequest = ormFunctions[origin].Alloc();
1501  if (ormRequest == NULL)
1502  {
1503  TRACE(TERROR, ("memory failure, or origin not supported; url=%s", url.data))
1504  callback(userData, invalid, 0);
1505  MHEG5stringDestruct( &url );
1506  }
1507  else
1508  {
1509  ormRequest->url = url;
1510  ormRequest->origin = origin;
1511  ormRequest->userData = userData;
1512  ormRequest->type = ORM_TYPE_POST;
1513  ormRequest->requestId = ++globalRequestId;
1514  ormRequest->r.post.postData = MHEG5stringCopy(postData);
1515  ormRequest->r.post.callback = callback;
1516 
1517  AddToRequestList(ormRequest);
1518  ormFunctions[origin].Action(ormRequest);
1519  if (ormRequest->state == ORM_STATE_FAILED)
1520  {
1521  TRACE(TFILE, ("Ptr=%p url=%s", ormRequest, url.data))
1522 
1523  requestDone = PostProcess(ormRequest);
1524  if (requestDone)
1525  {
1526  ormFunctions[origin].Clear(ormRequest);
1527  }
1528  }
1529  else if (ormRequest->state == ORM_STATE_REQUESTED)
1530  {
1531  TRACE(TFILE,("url = \"%s\"", (char *)url.data));
1532  success = MHEG5TRUE;
1533  }
1534  else
1535  {
1536  MHEG5stringDestruct( &url );
1537  ERROR_PRINT(("MHEG5FileOrmReturnData : Unexpected result\n"));
1538  }
1539  }
1540  }
1541  }
1542  return success;
1543 }
1544 
1545 #endif /* INCLUDE_IC */
1546 
1555 {
1556  MHEG5String url;
1557  E_FS_ORIGIN origin = DEFAULT_ORIGIN;
1558 #ifndef CI_PLUS_ONLY
1559  U8BIT *buffer;
1560 #endif
1561 
1562  /* Check that name is valid */
1563  if (!name.len)
1564  {
1565  /* Specified file name is empty */
1566  return;
1567  }
1568 
1569  /* Build absolute file name */
1570 #ifndef CI_PLUS_ONLY
1571  buffer = buildName(name, &url, &origin);
1572  if (origin == ORIGIN_DSM)
1573  {
1574  /* Pass the preload hint on to DSM-CC */
1575  DSMCC_ClientPreloadHint(MHEG5_DsmccInstance(), buffer);
1576  }
1577 #else
1578  buildName(name, &url, &origin);
1579 #endif
1580 
1581  MHEG5stringDestruct( &url );
1582 }
1583 
1584 #ifndef CI_PLUS_ONLY
1585 
1591 static void FileOrmDsmGetComplete( S_FileSystemAck *param )
1592 {
1593  S_OrmRequest *ormRequest;
1594  U_PARAM ud;
1595  ud.ptr = param->content.user_data;
1596  ormRequest = FindRequest(ud.u32);
1597  if (ormRequest != NULL)
1598  {
1599  assert(ormRequest->origin == ORIGIN_DSM);
1600  switch (param->status)
1601  {
1602  case FS_STATUS_OK:
1603  TRACE(TFILE, (" Got size=%d, for:%s", param->content.size, ormRequest->url.data));
1604  ormRequest->state = ORM_STATE_SUCCEEDED;
1605  ormRequest->r.get.ocontent = param->content;
1606  break;
1607 
1608  case FS_STATUS_INVALID:
1609  ormRequest->state = ORM_STATE_QUEUED;
1610  break;
1611 
1612  case FS_STATUS_ERROR:
1613  TRACE(TFILE, (" Failed to get %s", ormRequest->url.data));
1614  ormRequest->state = ORM_STATE_FAILED;
1615  break;
1616 
1617  case FS_STATUS_ABORT:
1618  TRACE(TFILE, (" ABORTED %s", ormRequest->url.data));
1619  if (ormRequest->state == ORM_STATE_REQUESTED)
1620  {
1621  ormRequest->state = ORM_STATE_FAILED;
1622  }
1623  /* else it should already be aborted state */
1624  break;
1625 
1626  case FS_STATUS_PENDING:
1627  TRACE(TERROR, (" STILL PENDING! %s", ormRequest->url.data))
1628  ormRequest->state = ORM_STATE_REQUESTED;
1629  break;
1630 
1631  default:
1632  /* An error ocurred */
1633  TRACE(TERROR, ("UNKNOWN return %d for %s", param->status, ormRequest->url.data))
1634  ormRequest->state = ORM_STATE_FAILED;
1635  }
1637  }
1638 }
1639 
1640 static void FileOrmDsmccComplete( E_FsStatus status, S_CONTENT *content )
1641 {
1642  S_MhegMessage msg;
1643 #ifdef TRACING
1644  S_OrmRequest *ormRequest;
1645  ormRequest = FindRequest((U32BIT)content->user_data);
1646  if (ormRequest != NULL)
1647  {
1648  TRACE(TFILE, ("ptr=%p url:%s size=%u", ormRequest, ormRequest->url.data, content->size ));
1649  }
1650  else
1651  {
1652  TRACE(TFILE, ("rid=%u size=%u",(U32BIT)content->user_data, content->size));
1653  }
1654 #endif
1655  msg.data.fsAck.content = *content;
1656  msg.data.fsAck.status = status;
1657  msg.proc_msg_func = (F_MSG_PROCESS)FileOrmDsmGetComplete;
1658  msg.data_type = DT_CONTENT;
1659  VQ_PutMsg(&msg, PRTY_NORMAL);
1660 }
1661 #endif /*CI_PLUS_ONLY*/
1662 
1663 #ifdef COMMON_INTERFACE
1664 
1671 void MHEG5ciFileAcknowledge(BOOLEAN fileOK, U8BIT *pFileData, U32BIT length)
1672 {
1673 #ifdef COMMON_INTERFACE
1674  S_OrmRequest *ormRequest;
1675  CiMessageContext *ciItem;
1676  U8BIT fileNameLength;
1677  char *url;
1678  BOOLEAN ack;
1679 
1680  DEBUG_PRINT(("MHEG5ciFileAcknowledge(%s, [%x %x], %d) ciRequestCount=%d\n",
1681  fileOK ? "TRUE" : "FALSE", pFileData[0], pFileData[1], length, ciRequestCount));
1682 
1683  /* Find context */
1684  ack = TRUE;
1685  if (pFileData != NULL && length > 0 && ciRequestCount > 0)
1686  {
1687  ciRequestCount--;
1688  if (ciAckTimerHandle != NULL)
1689  {
1690  VT_TimerDestroy( ciAckTimerHandle );
1691  ciAckTimerHandle = NULL;
1692  }
1693  if (pFileData[0] == 0x00 && length > 1) /* 'file' */
1694  {
1695  fileNameLength = pFileData[1];
1696 
1697  DEBUG_PRINT(("MHEG5ciFileAcknowledge: URL=%s\n", pFileData + 2));
1698 
1699  /* Could be either existence query or file request */
1700  ormRequest = requestListHead;
1701  while (ormRequest != NULL)
1702  {
1703  if (ormRequest->origin == ORIGIN_CI)
1704  {
1705  url = (char *)ormRequest->url.data;
1706  if ((ormRequest->url.len == fileNameLength) &&
1707  (strncmp(url, (char *)pFileData + 2, fileNameLength) == 0))
1708  {
1709  /* Found the file request */
1710  if (fileOK && CiSetFileContent(pFileData,length,&ormRequest->r.get.ocontent))
1711  {
1712  ormRequest->state = ORM_STATE_SUCCEEDED;
1713  /* We store the data, so do not acknowledge yet */
1714  ack = FALSE;
1715  }
1716  else
1717  {
1718  ormRequest->state = ORM_STATE_FAILED;
1719  if (ormRequest->type == ORM_TYPE_GET)
1720  {
1721  ormRequest->r.get.ocontent.size = 0;
1722  ormRequest->r.get.ocontent.data = NULL;
1723  }
1724  }
1725  break;
1726  }
1727  }
1728  ormRequest = ormRequest->next;
1729  }
1730  }
1731  else if (pFileData[0] == 0x01) /* 'data' */
1732  {
1733  /* We can now allow more messages to be sent */
1734  ciMessageSent = FALSE;
1735 
1736  /* CI data message */
1737  ciItem = ciMessageListHead;
1738  while (ciItem != NULL)
1739  {
1740  if (ciItem->successFlag == FS_STATUS_PENDING)
1741  {
1742  /* Mark message as received */
1743  ciItem->successFlag = FS_STATUS_OK;
1744  ciItem->output.len = length;
1745  ciItem->output.data = pFileData;
1746 
1747  /* We store the data, so do not acknowledge yet */
1748  ack = FALSE;
1749  break;
1750  }
1751  ciItem = ciItem->next;
1752  }
1753  }
1754  }
1755 
1756  if (ack && pFileData != NULL)
1757  {
1758  /* Release the data, it's not needed */
1759  MHEG5CiAckData(pFileData);
1760  }
1762 #endif /*COMMON_INTERFACE*/
1763 }
1764 #endif /*COMMON_INTERFACE*/
1765 
1766 #ifdef INCLUDE_IC
1767 
1777 static void HybridGetCallback( void *userData, S_CONTENT *ocontent )
1778 {
1779  S_OrmRequest *ormRequest;
1780 
1781  assert( userData );
1782  ormRequest = (S_OrmRequest *)userData;
1783  VERIFY_ORM_MAGIC(ormRequest);
1784  assert(ormRequest->type == ORM_TYPE_GET);
1785  ormRequest->r.get.ocontent = *ocontent;
1786 
1787  ocontent->destroy = NULL; /* don't let child request clear the data */
1788  ormRequest->r.get.child = NULL; /* after callback this pointer is no longer valid */
1789 
1790  ormRequest->state = ORM_STATE_SUCCEEDED;
1791  ReprocessRequestList();
1792 }
1793 
1801 static void HybridGetFailCallback( void *userData )
1802 {
1803  S_OrmRequest *ormRequest;
1804 
1805  assert( userData );
1806  ormRequest = (S_OrmRequest *)userData;
1807  VERIFY_ORM_MAGIC(ormRequest);
1808 
1809  assert(ormRequest->origin == ORIGIN_HYBRID);
1810  ormRequest->state = ORM_STATE_QUEUED;
1811  if (ormRequest->type != ORM_TYPE_POST)
1812  {
1813  ormRequest->r.get.child = NULL;
1814  }
1815 
1816  ReprocessRequestList();
1818 }
1819 
1830 static void httpRequestAck(U32BIT requestId, U32BIT status, S32BIT code,
1831  U8BIT *data, U32BIT len)
1832 {
1833  S_OrmRequest *ormRequest;
1834  void *fileRef;
1835  BOOLEAN releaseData;
1836 
1837  /* Release data unless we are storing it somewhere */
1838  releaseData = TRUE;
1839 
1840  ormRequest = FindRequest(requestId);
1841  if (ormRequest != NULL && (IS_HTTP_REQUEST(ormRequest)))
1842  {
1843  if (status == HTTP_STATUS_OK)
1844  {
1845  TRACE(TFILE, ("code=%d", code))
1846  if (((code >= 301) && (code <= 305)) || (code == 307))
1847  {
1848  if (ormRequest->type != ORM_TYPE_POST)
1849  {
1850  /* Redirect -- only GET or HEAD */
1851  HttpRedirect(ormRequest);
1852  }
1853  else
1854  {
1855  /* POST + redirection = failure */
1856  ormRequest->state = ORM_STATE_FAILED;
1857  TRACE(TFILE, ("POST redirect Ptr=%p FAIL url=%s", ormRequest, ormRequest->url.data))
1858  }
1859  }
1860  else if (code != 200)
1861  {
1862  if (code >= 400 && code < 500)
1863  {
1864  if (ormRequest->type == ORM_TYPE_POST ||
1865  !(ormRequest->r.get.priority & (FRP_HASH | FRP_CERT)))
1866  { /* Engine events should not be generated by "external" requests */
1867  MHEG5sendAppEngineEvent( EE_IC_REMOTE_ERROR );
1868  }
1869  }
1870  ormRequest->state = ORM_STATE_FAILED;
1871  TRACE(TFILE, ("Ptr=%p FAIL url=%s", ormRequest, ormRequest->url.data))
1872  }
1873  else
1874  {
1875  /* Update request data */
1876  if (ormRequest->type != ORM_TYPE_POST)
1877  {
1878  if (ormRequest->r.get.ocontent.data != NULL)
1879  {
1880  MHEG5freeMem(ormRequest->r.get.ocontent.data);
1881  }
1882 
1883  ormRequest->r.get.ocontent.data = data;
1884  ormRequest->r.get.ocontent.size = len;
1885  ormRequest->r.get.ocontent.destroy = DefaultDataClear;
1886  ormRequest->r.get.ocontent.fs_handle = data;
1887  releaseData = FALSE;
1888  }
1889 
1890  /* Check the content against the hash file */
1891  VerifyRequestContent(ormRequest);
1892  }
1893  }
1894  else if (status == HTTP_STATUS_SSL_ERROR)
1895  {
1896  /* Try again, maybe there are more certificates */
1897  ormRequest->state = ORM_STATE_QUEUED;
1898  ReprocessRequestList();
1899  }
1900  else if (status == HTTP_STATUS_NETWORK_ERROR)
1901  {
1902  if (ormRequest->type == ORM_TYPE_POST ||
1903  !(ormRequest->r.get.priority & FRP_HASH))
1904  { /* Engine events should not be generated by "external" requests */
1905  MHEG5sendAppEngineEvent( EE_IC_NETWORK_ERROR );
1906  }
1907  TRACE(TFILE, ("Network error Ptr=%p FAIL url=%s", ormRequest, ormRequest->url.data))
1908  ormRequest->state = ORM_STATE_FAILED;
1909  }
1910  else if (status == HTTP_STATUS_TIMEOUT)
1911  {
1912  /* Response code is modified for HTTP POST */
1913  TRACE(TFILE, ("response mod Ptr=%p FAIL url=%s", ormRequest, ormRequest->url.data))
1914  code = 0;
1915  ormRequest->state = ORM_STATE_FAILED;
1916  }
1917  else
1918  {
1919  TRACE(TFILE, ("status=%d Ptr=%p FAIL url=%s", status, ormRequest, ormRequest->url.data))
1920  ormRequest->state = ORM_STATE_FAILED;
1921  }
1922 
1923  if (ormRequest->type == ORM_TYPE_POST)
1924  {
1925  /* Update request */
1926  ormRequest->r.post.responseData.data = data;
1927  ormRequest->r.post.responseData.len = len;
1928  ormRequest->r.post.responseCode = code;
1929  releaseData = FALSE;
1930  }
1931 
1932  /* Destroy HTTP request */
1933  fileRef = ormRequest->requestRef;
1934  ormRequest->requestRef = NULL;
1935  httpStopRequest(fileRef);
1936  httpDestroyRequest(fileRef);
1937  }
1938  else
1939  {
1940  TRACE(TERROR, ("Cannot find request (requestId = %d)\n", requestId));
1941  }
1942 
1943  if (releaseData && data != NULL)
1944  {
1945  MHEG5freeMem(data);
1946  }
1947 }
1948 
1955 static void httpResponse(MHEG5HttpResponseEventParams_t *params)
1956 {
1957  httpRequestAck(params->requestId, params->status, params->code,
1958  params->data, params->len);
1960 }
1961 
1969 static BOOLEAN HttpGetCallback(void *userdata, U32BIT requestId,
1970  HttpResponse_t *response)
1971 {
1972  HttpReplyBuffer *hcontent = userdata;
1973  MHEG5eventMessage_t event;
1974  E_MhegErr cqu_err;
1975 
1976  if (response->data_len > 0)
1977  {
1978  AppendData(hcontent, response->data, response->data_len);
1979  }
1980 
1981  if (response->status != HTTP_STATUS_WAIT)
1982  {
1983  event.proc_msg_func = (F_MSG_PROCESS)httpResponse;
1984  event.data_type = DT_ALLOC;
1985  event.data.httpResponse.requestId = requestId;
1986  event.data.httpResponse.status = response->status;
1987  event.data.httpResponse.code = response->code;
1988  event.data.httpResponse.data = hcontent->data;
1989  event.data.httpResponse.len = hcontent->used;
1990 
1991  cqu_err = VQ_PutMsg(&event, PRTY_NORMAL);
1992  if (cqu_err != MHERR_OK)
1993  {
1994  TRACE(TERROR, ("VQ_PutMsg failed", cqu_err));
1995  MHEG5freeMem(hcontent->data);
1996  }
1997 
1998  MHEG5freeMem(hcontent);
1999  }
2000 
2001  return TRUE;
2002 }
2003 
2011 static BOOLEAN HttpPostCallback(void *userdata, U32BIT requestId,
2012  HttpResponse_t *response)
2013 {
2014  HttpReplyBuffer *hcontent = userdata;
2015  MHEG5eventMessage_t event;
2016  E_MhegErr cqu_err;
2017 
2018  if (response->data_len > 0)
2019  {
2020  AppendData(hcontent, response->data, response->data_len);
2021  }
2022 
2023  if (response->status != HTTP_STATUS_WAIT)
2024  {
2025  event.proc_msg_func = (F_MSG_PROCESS)httpResponse;
2026  event.data_type = DT_ALLOC;
2027  event.data.httpResponse.requestId = requestId;
2028  event.data.httpResponse.status = response->status;
2029  event.data.httpResponse.code = response->code;
2030  event.data.httpResponse.data = hcontent->data;
2031  event.data.httpResponse.len = hcontent->used;
2032 
2033  cqu_err = VQ_PutMsg(&event, PRTY_NORMAL);
2034  if (cqu_err != MHERR_OK)
2035  {
2036  TRACE(TERROR, ("VQ_PutMsg failed", cqu_err));
2037  MHEG5freeMem(hcontent->data);
2038  }
2039 
2040  MHEG5freeMem(hcontent);
2041  }
2042 
2043  return TRUE;
2044 }
2045 
2046 #endif /*INCLUDE_IC*/
2047 
2048 
2049 #ifndef CI_PLUS_ONLY
2050 
2055 static void DsmAction(S_OrmRequest *ormRequest)
2056 {
2057  E_FsStatus retval;
2058  U32BIT flags;
2059  U8BIT *path;
2060 
2061  assert(ormRequest->origin == ORIGIN_DSM);
2062 
2063  path = ormRequest->url.data + MHEG5FullOriginLength(ORIGIN_DSM);
2064 
2065  TRACE(TFILE,("Fetching url: %s", (char *)ormRequest->url.data));
2066 
2067  flags = ormRequest->r.get.priority & FRP_CACHE_MASK;
2068  if (ormRequest->r.get.priority & FRP_EXISTS)
2069  {
2070  flags |= LOAD_FLAGS_REQUEST_EXISTANCE_BIT;
2071  }
2072  if (ormRequest->r.get.priority & FRP_DEFER_SERV)
2073  {
2074  flags |= LOAD_FLAGS_REQUEST_DEFERRED_SERVICE_BIT;
2075  }
2076  if (ormRequest->r.get.priority & FRP_GROUP)
2077  {
2078  flags |= LOAD_FLAGS_REQUEST_FILE_ONLY_BIT;
2079  }
2080  retval = DSMCC_ClientLoadObject( MHEG5_DsmccInstance(), path, flags,
2081  FileOrmDsmccComplete, &ormRequest->r.get.ocontent );
2082  TRACE(TFILE, ("ref=%p Ptr=%p", ormRequest->requestRef, ormRequest))
2083  TRACE(TFILE, ("url=%s, rtn=%d", ormRequest->url.data, retval))
2084  switch (retval)
2085  {
2086  case FS_STATUS_OK:
2087  assert(ormRequest->requestRef == NULL);
2088  ormRequest->state = ORM_STATE_SUCCEEDED;
2089  ReprocessRequestList();
2090  break;
2091 
2092  case FS_STATUS_PENDING:
2093  TRACE(TFILE, (" loading %s", ormRequest->url.data));
2094  ormRequest->state = ORM_STATE_REQUESTED;
2095  ReprocessRequestList();
2096  break;
2097 
2098  case FS_STATUS_INVALID:
2099  /* File cannot be requested yet, as there is no carousel (and we're doing NDT) */
2100  ormRequest->state = ORM_STATE_QUEUED;
2101  break;
2102 
2103  default:
2104  /* An error ocurred */
2105  TRACE(TFILE, ("dsmFLoad(%s) retval is %d\n", ormRequest->url.data, retval));
2106  ormRequest->state = ORM_STATE_FAILED;
2107  ReprocessRequestList();
2108  }
2109 }
2110 
2111 #endif /* !CI_PLUS_ONLY */
2112 
2113 #ifndef CI_PLUS_ONLY
2114 
2119 static void DsmClear(S_OrmRequest *ormRequest)
2120 {
2121  VERIFY_ORM_MAGIC(ormRequest);
2122  assert(ormRequest->origin == ORIGIN_DSM);
2123 
2124  TRACE(TFILE, ("Ptr=%p url(%d)=%s", ormRequest,ormRequest->url.len,ormRequest->url.data))
2125 
2126  if (ormRequest->r.get.ocontent.destroy != NULL)
2127  {
2128  /* call the clear function for the content owner */
2129  ormRequest->r.get.ocontent.destroy( ormRequest->r.get.ocontent.fs_handle );
2130  }
2131  MHEG5stringDestruct( &ormRequest->url );
2132 
2133  CLEAR_ORM_MAGIC(ormRequest);
2134  MHEG5freeMem(ormRequest);
2135 }
2136 
2137 #endif /* !CI_PLUS_ONLY */
2138 
2144 static void DvbAction(S_OrmRequest *ormRequest)
2145 {
2146  MHEG5Bool success;
2147 
2148  assert(ormRequest->origin == ORIGIN_DVB || ormRequest->origin == ORIGIN_REC);
2149 
2150  /* Resolve the URL */
2151  success = MHEG5parseUrl(ormRequest->url.data, ormRequest->url.len,
2152  &dvbMultiplexReference );
2153  if (success)
2154  {
2155  ormRequest->r.get.ocontent.data = (U8BIT *)&dvbMultiplexReference;
2156  ormRequest->r.get.ocontent.size = sizeof(S_DVB_LOCATOR);
2157 
2158  /* there is no need to do any clear on data */
2159  assert( ormRequest->r.get.ocontent.destroy == NULL );
2160  assert( ormRequest->r.get.ocontent.fs_handle == NULL );
2161 
2162  ormRequest->state = ORM_STATE_SUCCEEDED;
2163  }
2164  else
2165  {
2166  ormRequest->state = ORM_STATE_FAILED;
2167  }
2168  ReprocessRequestList();
2169 }
2170 
2176 static void DvbClear(S_OrmRequest *ormRequest)
2177 {
2178  VERIFY_ORM_MAGIC(ormRequest);
2179  MHEG5stringDestruct( &ormRequest->url );
2180  assert(ormRequest->type == ORM_TYPE_GET);
2181 }
2182 
2183 #ifdef INCLUDE_IC
2184 
2190 static void HybrAction(S_OrmRequest *ormRequest)
2191 {
2192  MHEG5String reference;
2193  MHEG5String mapped;
2194  E_FS_ORIGIN origin;
2195  MHEG5Int offset;
2196 
2197  assert(ormRequest->origin == ORIGIN_HYBRID);
2198  assert(ormRequest->state == ORM_STATE_START);
2199 
2200  TRACE(TFILE,("Fetching url: %s", (char *)ormRequest->url.data));
2201 
2202  reference.len = ormRequest->url.len - 7;
2203  reference.data = ormRequest->url.data + 7;
2204 
2205  if (ormRequest->hybrid_mapping == NULL)
2206  {
2207  ormRequest->hybrid_mapping = MHEG5GetHybridFileSystemMapping(&reference);
2208  MHEG5InitMappingIter(&ormRequest->hybrid_iter, ormRequest->hybrid_mapping);
2209  }
2210 
2211  do {
2212  mapped = MHEG5GetNextReference(&reference, &ormRequest->hybrid_iter);
2213  if (mapped.len != 0)
2214  {
2215  ormRequest->state = ORM_STATE_REQUESTED;
2216  if (ormRequest->type == ORM_TYPE_FGR)
2217  {
2218  if (MHEG5ResolveOrigin(&mapped,&origin,&offset))
2219  {
2220  S_STRING path,name;
2221  path.zlen = mapped.len - offset;
2222  path.zptr = mapped.data + offset;
2223  name.zlen = 0;
2224  name.zptr = NULL;
2225  ormRequest->r.get.child = MHEG5FileOrmRetrieve( origin, path, name, ormRequest->r.get.priority,
2226  ormRequest, HybridGetCallback, HybridGetFailCallback );
2227  }
2228  }
2229  else
2230  {
2231  ormRequest->r.get.child = MHEG5FileOrmGet( mapped, ormRequest->r.get.priority, ormRequest,
2232  HybridGetCallback, HybridGetFailCallback );
2233  }
2234  MHEG5stringDestruct(&mapped);
2235  }
2236  else
2237  {
2238  MHEG5ReleaseHybridFileSystemMapping(ormRequest->hybrid_mapping);
2239  ormRequest->hybrid_mapping = NULL;
2240  ormRequest->state = ORM_STATE_FAILED;
2241  ReprocessRequestList();
2242  break;
2243  }
2244  /* ORM_STATE_QUEUED means HybridGetFailCallback was called synchronously,
2245  * so can loop here to move to next reference */
2246  } while (ormRequest->state == ORM_STATE_QUEUED);
2247 }
2248 
2254 static void HybrClear(S_OrmRequest *ormRequest)
2255 {
2256  VERIFY_ORM_MAGIC(ormRequest);
2257  assert(ormRequest->origin == ORIGIN_HYBRID);
2258 
2259  if (ormRequest->r.get.ocontent.destroy != NULL)
2260  {
2261  /* call the clear function for the content owner */
2262  ormRequest->r.get.ocontent.destroy( ormRequest->r.get.ocontent.fs_handle );
2263  }
2264  TRACE(TFILE,("ptr=%p url=\"%s\"",ormRequest,(char *)ormRequest->url.data));
2265  if (ormRequest->r.get.child != NULL)
2266  {
2267  S_OrmRequest *childRequest = (S_OrmRequest *)ormRequest->r.get.child;
2268 
2269  VERIFY_ORM_MAGIC(childRequest);
2270  assert(childRequest->userData == ormRequest);
2271 
2272  /* Remove and clear and child request */
2273  RemoveFromRequestList(childRequest);
2274  childRequest->state = ORM_STATE_ABORTED;
2275  ormFunctions[childRequest->origin].Clear(childRequest);
2276  }
2277  /* Release hybrid mapping */
2278  if (ormRequest->hybrid_mapping != NULL)
2279  {
2280  MHEG5ReleaseHybridFileSystemMapping(ormRequest->hybrid_mapping);
2281  ormRequest->hybrid_mapping = NULL;
2282  }
2283  MHEG5stringDestruct( &ormRequest->url );
2284 
2285  CLEAR_ORM_MAGIC(ormRequest);
2286  MHEG5freeMem(ormRequest);
2287 }
2288 
2289 #endif /* INCLUDE_IC */
2290 
2296 static MHEG5Bool DefaultGetProcess(S_OrmRequest *ormRequest)
2297 {
2298  MHEG5Bool requestDone;
2299 
2300  requestDone = MHEG5FALSE;
2301 
2302  if (ormRequest->state == ORM_STATE_SUCCEEDED)
2303  {
2304  /* Do not process groups when the engine is not active */
2305  if (MH5GlueActiveState() || !(ormRequest->r.get.priority & FRP_GROUP))
2306  {
2307  /* Remove the request from the list */
2308  RemoveFromRequestList(ormRequest);
2309 
2310  TRACE(TFILE, ("Ptr=%p GOT IT url=%s", ormRequest, ormRequest->url.data))
2311 
2312  /* Dump out all retrieved files in hex - useful for capturing ASN1 files
2313  * over serial port or on Windows application */
2314  PRINTFILE( ormRequest->type, ormRequest->url.data, ormRequest->r.get.ocontent.data, ormRequest->r.get.ocontent.size );
2315 
2316  /* Return file contents */
2317  ormRequest->r.get.cbGood( ormRequest->userData, &ormRequest->r.get.ocontent );
2318 
2319  requestDone = MHEG5TRUE;
2320  }
2321  else
2322  {
2323  TRACE(TFILE, ("Delay process of file, url=%s", ormRequest, ormRequest->url.data))
2324  }
2325  }
2326  else if (ormRequest->state == ORM_STATE_FAILED)
2327  {
2328  /* Remove the request from the list */
2329  RemoveFromRequestList(ormRequest);
2330 
2331  TRACE(TFILE, ("Ptr=%p FAIL url=%s", ormRequest, ormRequest->url.data))
2332 
2333  /* Notify that the load operation failed */
2334  if (ormRequest->r.get.cbFail != NULL)
2335  {
2336  ormRequest->r.get.cbFail( ormRequest->userData );
2337  }
2338  requestDone = MHEG5TRUE;
2339  }
2340  else if (ormRequest->state == ORM_STATE_ABORTED)
2341  {
2342  /* Remove the request from the list */
2343  RemoveFromRequestList(ormRequest);
2344 
2345  TRACE(TFILE, ("Ptr=%p ABORT url=%s", ormRequest, ormRequest->url.data))
2346 
2347  /* No notifications */
2348  requestDone = MHEG5TRUE;
2349  }
2350  else if (ormRequest->state == ORM_STATE_QUEUED ||
2351  ormRequest->state == ORM_STATE_HAS_ACCESS)
2352  {
2353  TRACE(TFILE, ("Ptr=%p QUEUE url=%s", ormRequest, ormRequest->url.data))
2354 
2355  /* Try again */
2356  ormRequest->state = ORM_STATE_START;
2357  ormFunctions[ormRequest->origin].Action(ormRequest);
2358  }
2359  else if (ormRequest->state == ORM_STATE_CHECK_VERIFY ||
2360  ormRequest->state == ORM_STATE_CHECK_ACCESS)
2361  {
2362  TRACE(TFILE, ("Ptr=%p OK url=%s", ormRequest, ormRequest->url.data))
2363 
2364  /* Must not restart request, as it already has content */
2365  ormFunctions[ormRequest->origin].Action(ormRequest);
2366  }
2367 
2368  return requestDone;
2369 }
2370 
2371 /*****************************************************************************/
2372 
2373 
2374 
2375 #ifdef INCLUDE_IC
2376 
2382 static void HttpRedirect(S_OrmRequest *ormRequest)
2383 {
2384  MHEG5String url;
2385  U8BIT *redirectUrl;
2386  E_FS_ORIGIN origin;
2387  MHEG5String name;
2388 
2389  assert(ormRequest->type != ORM_TYPE_POST && IS_HTTP_REQUEST(ormRequest));
2390 
2391  ormRequest->state = ORM_STATE_FAILED;
2392 
2393  if (ormRequest->redirectCount < MAX_REDIRECTS)
2394  {
2395  redirectUrl = httpGetRequestRedirect(ormRequest->requestRef);
2396  if (redirectUrl != NULL)
2397  {
2398  /* Build absolute file name */
2399  name.data = redirectUrl;
2400  name.len = strlen((char *)redirectUrl);
2401  buildName(name, &url, &origin);
2402  if ((origin == ORIGIN_HTTP) || (origin == ORIGIN_HTTPS))
2403  {
2404  MHEG5stringDestruct( &ormRequest->url );
2405  ormRequest->url = url;
2406  ormRequest->origin = origin;
2407 
2408  ++ormRequest->redirectCount;
2409  ormRequest->certCount = 0;
2410  ormRequest->state = ORM_STATE_QUEUED;
2411  ReprocessRequestList();
2412  }
2413  else
2414  {
2415  MHEG5stringDestruct( &url );
2416  }
2417  }
2418  }
2419 }
2420 
2426 static MHEG5Bool PostProcess(S_OrmRequest *ormRequest)
2427 {
2428  MHEG5Bool requestDone;
2429 
2430  assert(ormRequest->type == ORM_TYPE_POST);
2431 
2432  requestDone = MHEG5FALSE;
2433  if (ormRequest->state == ORM_STATE_SUCCEEDED ||
2434  ormRequest->state == ORM_STATE_FAILED)
2435  {
2436  /* Remove the request from the list */
2437  RemoveFromRequestList(ormRequest);
2438 
2439  ormRequest->r.post.callback(ormRequest->userData, ormRequest->r.post.responseData,
2440  ormRequest->r.post.responseCode);
2441 
2442  requestDone = MHEG5TRUE;
2443  }
2444  else if (ormRequest->state == ORM_STATE_CHECK_VERIFY ||
2445  ormRequest->state == ORM_STATE_CHECK_ACCESS)
2446  {
2447  /* Must not restart request, as it already has content */
2448  ormFunctions[ormRequest->origin].Action(ormRequest);
2449  }
2450 
2451  return requestDone;
2452 }
2453 
2454 #endif /* INCLUDE_IC */
2455 
2456 #ifdef COMMON_INTERFACE
2457 
2458 static BOOLEAN CiSetFileContent(U8BIT *data, U32BIT size, S_CONTENT *pContent)
2459 {
2460  U8BIT *fileData;
2461  U32BIT fileSize;
2462  U8BIT fileNameLength;
2463 
2464  /* File data must be processed */
2465  fileData = NULL;
2466  fileSize = 0;
2467  if (size > 1)
2468  {
2469  fileNameLength = data[1];
2470  if (size >= fileNameLength + 6U)
2471  {
2472  fileData = data + fileNameLength + 2;
2473  fileSize = (fileData[0] << 24 |
2474  fileData[1] << 16 |
2475  fileData[2] << 8 | fileData[3]);
2476  fileData += 4;
2477  if (size < fileSize + fileNameLength + 6)
2478  {
2479  fileData = NULL;
2480  fileSize = 0;
2481  }
2482  }
2483  }
2484  if (fileData == NULL)
2485  {
2486  return FALSE;
2487  }
2488  /* Return file contents */
2489  pContent->data = fileData;
2490  pContent->size = fileSize;
2491  pContent->destroy = (F_DESTROY)MHEG5CiAckData;
2492  pContent->fs_handle = (FS_HANDLE)fileData;
2493  return TRUE;
2494 }
2495 
2502 static void CiAction(S_OrmRequest *ormRequest)
2503 {
2504  U8BIT ciRequest[MHEG5_ABSOLUTE_PATH_LENGTH + 1];
2505  size_t length;
2506  S32BIT retval;
2507 
2508  assert(ormRequest->origin == ORIGIN_CI);
2509 
2510  ormRequest->state = ORM_STATE_FAILED;
2511  if (ciRequestCount < MAX_CI_REQUESTS)
2512  {
2513  /* Create CI file request */
2514  length = ormRequest->url.len;
2515  if (length <= MHEG5_ABSOLUTE_PATH_LENGTH)
2516  {
2517  ciRequest[0] = 0x00; /* 'file' */
2518  memcpy(&ciRequest[1], ormRequest->url.data, length);
2519 
2520  TRACE(TFILE, ("Ptr=%p len=%d url=%s", length,ormRequest->url.data))
2521 
2522  /* Request the file from the CAM */
2523  retval = STB_CIFileRequest(MHEG5GetCiModuleId(), ciRequest, length + 1);
2524  if (retval == TRUE)
2525  {
2526  /* File has been requested */
2527  ormRequest->state = ORM_STATE_REQUESTED;
2528  ciRequestCount++;
2529  }
2530  }
2531  }
2532  else
2533  {
2534  /* Cannot request at the moment */
2535  ormRequest->state = ORM_STATE_QUEUED;
2536  }
2537 }
2538 
2545 static void CiClear(S_OrmRequest *ormRequest)
2546 {
2547  VERIFY_ORM_MAGIC(ormRequest);
2548  assert( ormRequest->origin == ORIGIN_CI );
2549 
2550  TRACE(TFILE, ("Ptr=%p url(%d)=%s", ormRequest,ormRequest->url.len,ormRequest->url.data))
2551 
2552  if (ormRequest->r.get.ocontent.destroy != NULL)
2553  {
2554  /* call the clear function for the content owner */
2555  assert( ormRequest->r.get.ocontent.destroy == (F_DESTROY)MHEG5CiAckData );
2556  ormRequest->r.get.ocontent.destroy( ormRequest->r.get.ocontent.fs_handle );
2557  }
2558  MHEG5stringDestruct( &ormRequest->url );
2559 
2560  CLEAR_ORM_MAGIC(ormRequest);
2561  MHEG5freeMem(ormRequest);
2562 }
2563 
2564 #endif /*COMMON_INTERFACE*/
2565 
2566 #ifdef INCLUDE_IC
2567 
2575 static BOOLEAN HttpExistsCallback(void *userdata, U32BIT requestId,
2576  HttpResponse_t *response)
2577 {
2578  MHEG5eventMessage_t event;
2579  E_MhegErr cqu_err;
2580 
2581  if (response->status != HTTP_STATUS_WAIT)
2582  {
2583  event.proc_msg_func = (F_MSG_PROCESS)httpResponse;
2584  event.data_type = DT_VALUE;
2585  event.data.httpResponse.requestId = requestId;
2586  event.data.httpResponse.status = response->status;
2587  event.data.httpResponse.code = response->code;
2588  event.data.httpResponse.data = NULL;
2589  event.data.httpResponse.len = 0;
2590 
2591  cqu_err = VQ_PutMsg(&event, PRTY_NORMAL);
2592  if (cqu_err != MHERR_OK)
2593  {
2594  TRACE(TERROR, ("VQ_PutMsg failed", cqu_err));
2595  }
2596  }
2597  return TRUE;
2598 }
2599 
2606 static void HttpAction(S_OrmRequest *ormRequest)
2607 {
2608  MHEG5Bool connectionEnabled;
2609 
2610  assert(IS_HTTP_REQUEST(ormRequest));
2611 
2612  TRACE(TFILE,("Fetching / checking url \"%s\"", (char *)ormRequest->url.data));
2613 
2614  /* Check whether connection is allowed */
2615  MHEG5isConnectionEnabled(&connectionEnabled);
2616  if (connectionEnabled)
2617  {
2618  /* IC is Active */
2619  TRACE(TFILE,("[1] state = %s\n", ORM_STATE_STRING(ormRequest)));
2620  if (ormRequest->state == ORM_STATE_START ||
2621  ormRequest->state == ORM_STATE_CHECK_ACCESS)
2622  {
2623  CheckServerAccess(ormRequest);
2624  }
2625  TRACE(TFILE,("[2] state = %s\n", ORM_STATE_STRING(ormRequest)));
2626  if (ormRequest->state == ORM_STATE_HAS_ACCESS)
2627  {
2628  CheckTlsCertificates(ormRequest);
2629  }
2630  TRACE(TFILE,("[3] state = %s\n", ORM_STATE_STRING(ormRequest)));
2631  if (ormRequest->state == ORM_STATE_HAS_CERT)
2632  {
2633  PerformHttpRequest(ormRequest);
2634  }
2635  TRACE(TFILE,("[4] state = %s\n", ORM_STATE_STRING(ormRequest)));
2636  if (ormRequest->state == ORM_STATE_CHECK_VERIFY)
2637  {
2638  VerifyRequestContent(ormRequest);
2639  }
2640  TRACE(TFILE,("[5] state = %s\n", ORM_STATE_STRING(ormRequest)));
2641  if (ormRequest->state == ORM_STATE_FAILED)
2642  {
2643  ReprocessRequestList();
2644  }
2645  }
2646  else
2647  {
2648  /* IC is not active */
2649  if (ormRequest->type == ORM_TYPE_POST ||
2650  !(ormRequest->r.get.priority & FRP_HASH))
2651  { /* Engine events should not be generated by "external" requests */
2652  MHEG5sendAppEngineEvent( EE_IC_LOCAL_ERROR );
2653  }
2654  ormRequest->state = ORM_STATE_FAILED;
2655  ReprocessRequestList();
2656  }
2657 }
2658 
2665 static void HttpClear(S_OrmRequest *ormRequest)
2666 {
2667  VERIFY_ORM_MAGIC(ormRequest);
2668  assert(IS_HTTP_REQUEST(ormRequest));
2669 
2670  TRACE(TFILE, ("Ptr=%p url(%d)=%s", ormRequest,ormRequest->url.len,ormRequest->url.data))
2671 
2672  if (ormRequest->state == ORM_STATE_REQUESTED)
2673  {
2674  httpStopRequest(ormRequest->requestRef);
2675  httpDestroyRequest(ormRequest->requestRef);
2676  ormRequest->requestRef = NULL;
2677  }
2678 
2679  if (ormRequest->type == ORM_TYPE_GET || ormRequest->type == ORM_TYPE_FGR)
2680  {
2681  if (ormRequest->r.get.ocontent.destroy != NULL)
2682  {
2683  /* call the clear function for the content owner */
2684  ormRequest->r.get.ocontent.destroy(ormRequest->r.get.ocontent.fs_handle );
2685  }
2686  }
2687  else if (ormRequest->type == ORM_TYPE_POST)
2688  {
2689  if (ormRequest->r.post.responseData.data != NULL)
2690  {
2691  MHEG5freeMem(ormRequest->r.post.responseData.data);
2692  }
2693  MHEG5stringDestruct(&ormRequest->r.post.postData);
2694  }
2695 
2696  MHEG5stringDestruct( &ormRequest->url );
2697 
2698  CLEAR_ORM_MAGIC(ormRequest);
2699  MHEG5freeMem(ormRequest);
2700 }
2701 
2708 static void CheckServerAccess(S_OrmRequest *ormRequest)
2709 {
2710  MHEG5ServerAccess_t permission;
2711  BOOLEAN check;
2712 
2713  check = TRUE;
2714 
2715  if (ormRequest->redirectCount > 0)
2716  {
2717  /* Redirections are not checked */
2718  check = FALSE;
2719  }
2720  else if (ormRequest->type != ORM_TYPE_POST)
2721  {
2722  if (ormRequest->r.get.priority & (FRP_HASH | FRP_CERT))
2723  {
2724  /* Special files are not checked */
2725  check = FALSE;
2726  }
2727  }
2728 
2729  if (check)
2730  {
2731  /* Check server access */
2732  ormRequest->state = ORM_STATE_WAIT_ACCESS;
2733  permission = MHEG5CheckServerPermitted(ormRequest->url.data);
2734  switch (permission)
2735  {
2737  ormRequest->state = ORM_STATE_HAS_ACCESS;
2738  break;
2740  ormRequest->state = ORM_STATE_HAS_ACCESS;
2741  if (ormRequest->type != ORM_TYPE_POST)
2742  {
2743  ormRequest->r.get.priority &= ~FRP_VERIFY;
2744  }
2745  break;
2746  case SERVER_ACCESS_BLOCKED:
2747  ormRequest->state = ORM_STATE_FAILED;
2748  break;
2749  case SERVER_ACCESS_PENDING:
2750  break;
2751  default:
2752  PRINT_ERROR(("Invalid server access permission\n"));
2753  assert(0);
2754  }
2755  }
2756  else
2757  {
2758  ormRequest->state = ORM_STATE_HAS_ACCESS;
2759  }
2760 }
2761 
2772 static void CheckTlsCertificates(S_OrmRequest *ormRequest)
2773 {
2774  U32BIT certCount;
2776 
2777  if (IS_HTTPS_REQUEST(ormRequest))
2778  {
2779  /* Check TLS certificates */
2780  ormRequest->state = ORM_STATE_WAIT_CERT;
2781 
2782  certCount = MHEG5GetTlsCertStoreCount();
2783  if (certCount == 0 || ormRequest->certCount == certCount)
2784  {
2785  /* Either no certificates, or no new certificates - request
2786  * next certificate
2787  */
2788  status = MHEG5GetNextTlsCertificate();
2789  if (status == MHEG5_TLS_CERT_REQUEST_SUCCESS)
2790  {
2791  /* New certificates obtained (synchronously) */
2792  ormRequest->certCount = MHEG5GetTlsCertStoreCount();
2793  ormRequest->state = ORM_STATE_HAS_CERT;
2794  }
2795  else if (status == MHEG5_TLS_CERT_REQUEST_FAILURE)
2796  {
2797  ormRequest->state = ORM_STATE_FAILED;
2798  }
2799  }
2800  else if (ormRequest->certCount < certCount)
2801  {
2802  /* No need to request new certificates */
2803  ormRequest->certCount = certCount;
2804  ormRequest->state = ORM_STATE_HAS_CERT;
2805  }
2806  }
2807  else
2808  {
2809  /* HTTP requests don't need to check certificates */
2810  ormRequest->state = ORM_STATE_HAS_CERT;
2811  }
2812 }
2813 
2819 static void PerformHttpRequest(S_OrmRequest *ormRequest)
2820 {
2821  HttpRequest_t httpRequest;
2822  U8BIT *postData;
2823  HttpReplyBuffer *hcontent;
2824  U16BIT priority;
2825  U8BIT cachePriority;
2826 
2827  hcontent = NULL;
2828  if (ormRequest->type != ORM_TYPE_POST)
2829  {
2830  priority = ormRequest->r.get.priority;
2831  }
2832  else
2833  {
2834  priority = 0;
2835  }
2836  if (!(priority & FRP_EXISTS))
2837  {
2838  /* Requests with hcontent need a placeholder for the content */
2839  hcontent = MHEG5getMem(sizeof *hcontent);
2840  if (hcontent != NULL)
2841  {
2842  hcontent->allocated = 0;
2843  hcontent->used = 0;
2844  hcontent->data = NULL;
2845  hcontent->valid = TRUE;
2846  }
2847  else
2848  {
2849  ormRequest->state = ORM_STATE_FAILED;
2850  }
2851  }
2852  if (ormRequest->state != ORM_STATE_FAILED)
2853  {
2854  /* Perform the actual request */
2855  httpRequest = NULL;
2856  if (priority & FRP_EXISTS)
2857  {
2858  httpRequest = httpCreateHeadRequest(ormRequest->url.data,
2859  HttpExistsCallback,
2860  ormRequest->requestId, NULL);
2861  }
2862  else if (ormRequest->type != ORM_TYPE_POST)
2863  {
2864  if ((ormRequest->r.get.priority & (FRP_GROUP | FRP_CACHE_MASK))
2865  == FRP_GROUP)
2866  {
2867  /* For groups, cache priority 0 is transparent caching */
2868  cachePriority = 1;
2869  }
2870  else
2871  {
2872  cachePriority = ormRequest->r.get.priority & FRP_CACHE_MASK;
2873  }
2874  httpRequest = httpCreateGetRequest(ormRequest->url.data,
2875  cachePriority,
2876  HttpGetCallback,
2877  ormRequest->requestId, hcontent);
2878  TRACE(TFILE,("httpRequest =%p", httpRequest));
2879  }
2880  else // if (ormRequest->type == ORM_TYPE_POST)
2881  {
2882  postData = ormRequest->r.post.postData.data;
2883  httpRequest = httpCreatePostRequest(ormRequest->url.data,
2884  postData,
2885  HttpPostCallback,
2886  ormRequest->requestId, hcontent);
2887  }
2888 
2889  if (httpRequest != NULL)
2890  {
2891  ormRequest->requestRef = httpRequest;
2892  ormRequest->state = ORM_STATE_REQUESTED;
2893  httpStartRequest(httpRequest);
2894  }
2895  else
2896  {
2897  MHEG5freeMem(hcontent);
2898  ormRequest->state = ORM_STATE_FAILED;
2899  }
2900  }
2901 }
2902 
2908 static void VerifyRequestContent(S_OrmRequest *ormRequest)
2909 {
2911  TRACE(TFILE, (""))
2912  if ((ormRequest->type == ORM_TYPE_GET || ormRequest->type == ORM_TYPE_FGR) &&
2913  !(ormRequest->r.get.priority & FRP_EXISTS))
2914  {
2915  if (ormRequest->r.get.priority & FRP_HASH)
2916  {
2917  /* Hash requests are always ok, otherwise we have an infinite loop */
2918  ormRequest->state = ORM_STATE_SUCCEEDED;
2919  }
2920  else if (ormRequest->r.get.priority & (FRP_VERIFY | FRP_GROUP))
2921  {
2922  TRACE(TFILE,("Checking %s\n", ormRequest->url.data));
2923  status = MHEG5IsContentVerified( ormRequest->url.data, ormRequest->r.get.ocontent.data,
2924  ormRequest->r.get.ocontent.size );
2925  switch (status)
2926  {
2928  TRACE(TFILE,("CONTENT_NOT_VERIFIED_SAME\n"));
2929  ormRequest->state = ORM_STATE_FAILED;
2930  MHEG5ResetHashFile(ormRequest->url.data);
2931  ReprocessRequestList();
2932  break;
2934  TRACE(TFILE,("CONTENT_NOT_VERIFIED_NEW\n"));
2935  /* Failed verification, try again (from the start) */
2936  ormRequest->state = ORM_STATE_QUEUED;
2937  ormRequest->certCount = 0;
2938  MHEG5ResetHashFile(ormRequest->url.data);
2939  ReprocessRequestList();
2940  break;
2942  TRACE(TFILE,("CONTENT_VERIFIED_SIGNED\n"));
2943  ormRequest->state = ORM_STATE_SUCCEEDED;
2944  MHEG5ResetHashFile(ormRequest->url.data);
2945  ReprocessRequestList();
2946  break;
2948  TRACE(TFILE,("CONTENT_VERIFIED_UNSIGNED\n"));
2949  if (ormRequest->r.get.priority & FRP_GROUP)
2950  {
2951  /* Groups must be signed */
2952  ormRequest->state = ORM_STATE_FAILED;
2953  }
2954  else
2955  {
2956  /* Content can be unsigned */
2957  ormRequest->state = ORM_STATE_SUCCEEDED;
2958  }
2959  MHEG5ResetHashFile(ormRequest->url.data);
2960  ReprocessRequestList();
2961  break;
2963  TRACE(TFILE,("CONTENT_VERIFICATION_PENDING\n"));
2964  ormRequest->state = ORM_STATE_WAIT_VERIFY;
2965  break;
2966  }
2967  }
2968  else
2969  {
2970  TRACE(TFILE, (""))
2971  /* Server access file indicated that content verification is
2972  * not required, and the request is for content (not group).
2973  */
2974  ormRequest->state = ORM_STATE_SUCCEEDED;
2975  }
2976  }
2977  else
2978  {
2979  TRACE(TFILE, (""))
2980  /* Content is only verified for 'Get' requests */
2981  ormRequest->state = ORM_STATE_SUCCEEDED;
2982  }
2983 }
2984 
2990 static void TlsCertCallback(void)
2991 {
2992  S_OrmRequest *ormRequest;
2993 
2994  ormRequest = requestListHead;
2995  while (ormRequest != NULL)
2996  {
2997  if (ormRequest->state == ORM_STATE_WAIT_CERT)
2998  {
2999  assert(IS_HTTPS_REQUEST(ormRequest));
3000  ormRequest->state = ORM_STATE_QUEUED;
3001  ReprocessRequestList();
3002  }
3003  ormRequest = ormRequest->next;
3004  }
3005 }
3006 
3012 static void ServerAccessCallback(void)
3013 {
3014  S_OrmRequest *ormRequest;
3015 
3016  ormRequest = requestListHead;
3017  while (ormRequest != NULL)
3018  {
3019  if ((IS_HTTP_REQUEST(ormRequest)) &&
3020  (ormRequest->state == ORM_STATE_WAIT_ACCESS))
3021  {
3022  ormRequest->state = ORM_STATE_CHECK_ACCESS;
3023  }
3024  ormRequest = ormRequest->next;
3025  }
3026  ReprocessRequestList();
3027 }
3028 
3034 static void VerificationCallback(void)
3035 {
3036  S_OrmRequest *ormRequest;
3037 
3038  ormRequest = requestListHead;
3039  while (ormRequest != NULL)
3040  {
3041  if ((IS_HTTP_REQUEST(ormRequest)) &&
3042  (ormRequest->state == ORM_STATE_WAIT_VERIFY))
3043  {
3044  ormRequest->state = ORM_STATE_CHECK_VERIFY;
3045  }
3046  ormRequest = ormRequest->next;
3047  }
3048  ReprocessRequestList();
3049 }
3050 
3058 static void AppendData(HttpReplyBuffer *hcontent, U8BIT *data, U32BIT dataLen)
3059 {
3060  U32BIT size;
3061  U8BIT *new_data;
3062 
3063  if (hcontent->valid)
3064  {
3065  if (hcontent->allocated == 0)
3066  {
3067  size = dataLen;
3068 
3069  /* This finds the next power of two */
3070  --size;
3071  size |= size >> 16;
3072  size |= size >> 8;
3073  size |= size >> 4;
3074  size |= size >> 2;
3075  size |= size >> 1;
3076  ++size;
3077 
3078  if (size < MIN_HTTP_REPLY_BLOCK)
3079  {
3080  size = MIN_HTTP_REPLY_BLOCK;
3081  }
3082  hcontent->data = MHEG5getMem(size + 1);
3083  if (hcontent->data != NULL)
3084  {
3085  hcontent->allocated = size;
3086  hcontent->used = dataLen;
3087  memcpy(hcontent->data, data, dataLen);
3088  hcontent->data[hcontent->used] = '\0';
3089  }
3090  }
3091  else if (hcontent->allocated >= hcontent->used + dataLen)
3092  {
3093  memcpy(hcontent->data + hcontent->used, data, dataLen);
3094  hcontent->used += dataLen;
3095  }
3096  else
3097  {
3098  size = hcontent->allocated;
3099  do
3100  {
3101  size *= 2;
3102  }
3103  while (size < hcontent->used + dataLen);
3104  new_data = MHEG5getMem(size + 1);
3105  if (new_data != NULL)
3106  {
3107  memcpy(new_data, hcontent->data, hcontent->used);
3108  memcpy(new_data + hcontent->used, data, dataLen);
3109  MHEG5freeMem(hcontent->data);
3110  hcontent->allocated = size;
3111  hcontent->used += dataLen;
3112  hcontent->data = new_data;
3113  hcontent->data[hcontent->used] = '\0';
3114  }
3115  else
3116  {
3117  MHEG5freeMem(hcontent->data);
3118  hcontent->used = 0;
3119  hcontent->allocated = 0;
3120  hcontent->valid = FALSE;
3121  }
3122  }
3123  }
3124 }
3125 
3126 #endif /* INCLUDE_IC */
3127 
3132 static void ReprocessRequestList(void)
3133 {
3134  if (inprocess)
3135  {
3136  reprocess = TRUE;
3137  }
3138  else
3139  {
3141  }
3142 }
3143 
3148 static void ProcessRequestList(void)
3149 {
3150  S_OrmRequest *ormRequest;
3151  MHEG5Bool requestDone;
3152 
3153  ormRequest = requestListHead;
3154  while (ormRequest != NULL)
3155  {
3156  requestDone =
3157  #ifdef INCLUDE_IC
3158  (ormRequest->type == ORM_TYPE_POST)? PostProcess(ormRequest) :
3159  #endif
3160  DefaultGetProcess(ormRequest);
3161  if (requestDone)
3162  {
3163  /* Clear request */
3164  ormFunctions[ormRequest->origin].Clear(ormRequest);
3165 
3166  /* Start from the beginning */
3167  ormRequest = requestListHead;
3168  }
3169  else
3170  {
3171  ormRequest = ormRequest->next;
3172  }
3173  }
3174 }
3175 
3176 #if !defined(CI_PLUS_ONLY) || defined(INCLUDE_IC)
3177 
3182 static S_OrmRequest* FindRequest(U32BIT requestId)
3183 {
3184  S_OrmRequest *ormRequest;
3185 
3186  ormRequest = requestListHead;
3187  while (ormRequest != NULL)
3188  {
3189  if (ormRequest->requestId == requestId)
3190  {
3191  break;
3192  }
3193  ormRequest = ormRequest->next;
3194  }
3195 
3196  return ormRequest;
3197 }
3198 #endif
Implement MHEG5 engine control functions (i.e. start/stop etc)
E_MhegErr VQ_PutMsg(S_MhegMessage *pMsg, E_PRIORITY priority)
Post event or section message on queue. Copies data into queue.
Definition: glue_queue.c:248
void MHEG5AddTlsCertificateCallback(void(*loadCallback)(void))
Add a callback function to be called when pending requests are resolved.
Definition: mh5tls.c:189
MHEG5ContentVerification_t MHEG5IsContentVerified(U8BIT *url, U8BIT *content, U32BIT length)
Definition: mh5hash.c:184
BOOLEAN MH5GlueActiveState(void)
Definition: glue_main.c:993
void(* Clear)(P_OrmRequest request)
Definition: mh5fileorm.c:233
void MHEG5sendAppEngineEvent(E_ENGINE_EVENT engine_event)
Store an Engine event in the asynchronous event queue.
Definition: mh5queue.c:1633
P_OrmRequest(* Alloc)(void)
Definition: mh5fileorm.c:231
union sOrmRequest::@10 r
MHEG5String postData
Definition: mh5fileorm.c:250
F_MSG_PROCESS proc_msg_func
Definition: glue_queue.h:198
Functions relating to HTTPS Signature Certificates.
F_DESTROY destroy
Definition: fs_types.h:56
#define HybrAlloc
Definition: mh5fileorm.c:106
U32BIT size
Definition: fs_types.h:54
File acceleration for Australia and Souh Africa.
MHEG5TlsCertRequestStatus
Definition: mh5tls.h:37
Interface functions to DSM-CC instance for MHEG5.
MHEG5Int responseCode
Definition: mh5fileorm.c:251
void httpStartRequest(HttpRequest_t request)
Start an HTTP request. Everything related to the request is passed through the callback that was regi...
#define CiClear
Definition: mh5fileorm.c:334
Manages the interface between MHEG5 Engine and the HTTP component.
E_MhegErr VT_TimerCreate(U32BIT millisecs, F_TimerCallback callback, void *callerRef, H_Timer *pTimerHandle)
Set a timer for a certain number of millseconds. When the timer expires a specified callback will be ...
Definition: glue_timers.c:223
#define ORIGIN_MAX
Definition: mh5gate.h:41
MHEG5Bool MHEG5ResolveOrigin(MHEG5String *ref, E_FS_ORIGIN *pOrigin, MHEG5Int *offset)
Resolve the origin of a reference.
Definition: mh5gate.c:208
U16BIT priority
Definition: mh5fileorm.c:243
void * ptr
Definition: glue_type.h:38
const char * data
Definition: mh5gate.c:56
MHEG5FileOrmResetMode
Definition: mh5fileorm.h:54
MHEG5ServerAccess_t
Definition: mh5access.h:36
E_OrmState
Definition: mh5fileorm.c:177
void(* F_CB_Good)(void *userData, S_CONTENT *content)
Definition: mh5fileorm.h:61
void * H_Timer
Definition: glue_timers.h:58
U32BIT requestId
Definition: mh5fileorm.c:267
#define INFO_PRINT(x)
Definition: mh5debug.h:69
E_HttpStatus status
void MHEG5ciFileAcknowledge(BOOLEAN fileOK, U8BIT *pFileData, U32BIT length)
Process the FileAcknowledge message sent from the CI module.
P_OrmRequest child
Definition: mh5fileorm.c:242
void(* F_DESTROY)(FS_HANDLE fs_handle)
Definition: fs_types.h:47
MHEG5Bool MHEG5parseUrl(U8BIT *buffer, U32BIT length, S_DVB_LOCATOR *multiplexRef)
Parse a DAVIC style multiplex reference or UK-DTT inherritance format URL. This can be one of the fol...
Definition: mh5misc.c:106
MHEG5Int MHEG5FullOriginLength(E_FS_ORIGIN origin)
Get length for origin (e.g. "DSM://" is 6)
Definition: mh5gate.c:192
MHEG5 queue.
HttpRequest_t httpCreateHeadRequest(U8BIT *url, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP HEAD request.
unsigned char * STR_DataAlloc(unsigned int size)
Definition: glue_memory.c:596
#define FRP_DEFER_SERV
Definition: mh5fileorm.h:48
Implement the MHEG5 Stream Class Stream Class Defines the behaviour of a composition of continuous me...
E_OrmType type
Definition: mh5fileorm.c:262
#define MHEG5getMem
Definition: glue_memory.h:93
#define PRINT_ERROR(x)
Definition: mh5fileorm.c:144
Definition: mh5fileorm.c:247
E_FsStatus FG_LoadRequest(E_FS_ORIGIN origin, const char *fname, F_FS_CALLBACK cb_func, S_CONTENT *pContent, U8BIT cachePriority)
Request file from file group stores.
void MHEG5InitMappingIter(MHEG5MappingIter_t *iter, void *mapping)
Initialise hybrid filesystem mapping iterator.
Definition: mh5hfs.c:283
#define FRP_CACHE_MASK
Definition: mh5fileorm.h:39
void(* F_CB_Post)(void *userData, MHEG5String responseData, MHEG5Int responseCode)
Definition: mh5fileorm.h:63
Miscellaneous.
void * MHEG5_DsmccInstance(void)
Get the DSMCC instance handle.
Definition: glue_dsmcc.c:778
void(* F_CB_CiMsg)(void *userData, MHEG5String output, MHEG5Bool success)
Definition: mh5fileorm.h:64
MHEG5Bool MHEG5streamGetCurrentService(S_DVB_LOCATOR *multiplexRef)
Return the current service (i.e. the service corresponding to the currently running Video...
Definition: mh5stream.c:1098
U8BIT * zptr
Definition: dtvstring.h:31
U16BIT transport_stream_id
Definition: dvblocator.h:33
#define HybrAction
Definition: mh5fileorm.c:377
E_MhegErr
Definition: mherrors.h:28
struct S_DvbLocator S_DVB_LOCATOR
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
Definition: mh5base.c:574
void(* Action)(P_OrmRequest request)
Definition: mh5fileorm.c:232
void * FS_HANDLE
Definition: fs_types.h:46
BOOLEAN MHEG5FileOrmProcess(void)
Check for any file requests that have arrived since this function was last called. For each arrived file the callback will be called. The function may have to be called more than once in case a file the arrived affects other files as well.
Definition: mh5fileorm.c:830
MHEG5TlsCertRequestStatus MHEG5GetNextTlsCertificate(void)
Issues a request to load the next TLS certificate from the DSM-CC object carousel.
Definition: mh5tls.c:126
S_CONTENT ocontent
Definition: mh5fileorm.c:241
void MHEG5FileOrmPreloadHint(MHEG5String name)
Provide a preload hint to DSM-CC that the specified file may be required in the future. DSM-CC could (but is not required to) acquire the file into cache.
Definition: mh5fileorm.c:1554
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
void(* F_MSG_PROCESS)(void *data)
Function to Process voyager message.
Definition: glue_queue.h:70
#define FRP_EXISTS
Definition: mh5fileorm.h:43
#define HttpClear
Definition: mh5fileorm.c:380
U16BIT original_network_id
Definition: dvblocator.h:32
uint8_t U8BIT
Definition: techtype.h:82
struct CiMessageContext_struct * next
Definition: mh5fileorm.c:211
long MHEG5Int
Definition: mh5base.h:73
#define MAX_REDIRECTS
Definition: mh5fileorm.c:87
F_CB_Good cbGood
Definition: mh5fileorm.c:239
void(* F_TimerCallback)(BOOLEAN triggered, void *callerRef, H_Timer timerHandle)
Definition: glue_timers.h:77
E_FsStatus status
Definition: glue_queue.h:134
struct sOrmRequest * P_OrmRequest
Definition: mh5fileorm.c:227
void MHEG5SetVerificationCallback(void(*callback)(void))
Register a callback to be fired when the state of the verification subsystem changes.
Definition: mh5hash.c:128
#define FRP_IN_APP
Definition: mh5fileorm.h:49
Memory functions.
DVB Service information functions are required by MHEG5 engine. All required functions should be non-...
struct sOrmPostRequest S_OrmPostRequest
#define IS_HTTP_REQUEST(r)
Definition: mh5fileorm.c:119
#define MHEG5freeMem
Definition: glue_memory.h:94
void * STB_MemAlloc(U32BIT memSize)
Allocates the specified number of bytes.
U8BIT * httpGetRequestRedirect(HttpRequest_t request)
Return the URL that the request is redirected to (valid only for response codes of 3xx)...
This file defines the profile for the MHEG engine.
#define CiAlloc
Definition: mh5fileorm.c:98
#define CiAction
Definition: mh5fileorm.c:333
void MHEG5AddServerAccessCallback(void(*LoadNotifyCallback)(void))
Add callback function to be called when the server access permission file is loaded.
Definition: mh5access.c:344
S_CONTENT content
Definition: glue_queue.h:133
void MHEG5FileOrmInit(void)
Initialise the file ORM module.
Definition: mh5fileorm.c:576
void STR_DataFree(unsigned char *data, unsigned int size)
Definition: glue_memory.c:668
HttpRequest_t httpCreatePostRequest(U8BIT *url, U8BIT *data, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP POST request.
Implement Functions to support Service Gateways. Functions for standarizing several GroupIDs like +DS...
E_OrmType
Definition: mh5fileorm.c:195
#define HttpAlloc
Definition: mh5fileorm.c:105
#define VERIFY_ORM_MAGIC(r)
Definition: mh5fileorm.c:131
short MHEG5Bool
Definition: mh5base.h:71
#define DEFAULT_ORIGIN
Definition: mh5fileorm.c:113
MHEG5String MHEG5convertGIDGetOrigin(MHEG5String *inRef, E_FS_ORIGIN *pOrigin)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:282
#define FRP_SERVER
Definition: mh5fileorm.h:47
U32BIT u32
Definition: glue_type.h:39
struct CiMessageContext_struct CiMessageContext
MHEG5ServerAccess_t MHEG5CheckServerPermitted(U8BIT *url)
Definition: mh5access.c:111
Event handling. Implementation of a combined queue for events and actions. This is the eventsystem wh...
E_OrmState state
Definition: mh5fileorm.c:263
Functions relating to HTTPS Server Access.
Functions relating to HTTPS Content Verification.
#define DsmAlloc
Definition: mh5fileorm.c:90
MHEG5Byte * data
Definition: mh5base.h:85
void httpStopRequest(HttpRequest_t request)
Stop an HTTP request. This function does not destroy the request; this is done using httpDestroyReque...
int len
Definition: mh5gate.c:57
void * userData
Definition: mh5fileorm.c:265
void(* F_CB_Fail)(void *userData)
Definition: mh5fileorm.h:62
void MHEG5ResetHashFile(U8BIT *url)
Reset the state and clear cache of the hashfile associated with a content file.
Definition: mh5hash.c:874
void * MHEG5FileOrmRetrieve(E_FS_ORIGIN origin, S_STRING location, S_STRING name, U16BIT priority, void *userData, F_CB_Good cbGood, F_CB_Fail cbFail)
Retrieve of a file. The file will be loaded and one of the callback functions called when request is ...
Definition: mh5fileorm.c:1290
int32_t S32BIT
Definition: techtype.h:87
#define MHEG5TRUE
Definition: mh5base.h:49
E_DATA_TYPE data_type
Definition: glue_queue.h:199
struct sOrmRequest S_OrmRequest
void * requestRef
Definition: mh5fileorm.c:264
#define IS_HTTPS_REQUEST(r)
Definition: mh5fileorm.c:120
#define MHEG5strncmp(a, b, n)
Definition: mh5base.h:52
uint16_t U16BIT
Definition: techtype.h:84
Implement functions to retrieve MHEG5objects by GroupID and ID.
void MHEG5FileOrmClear(void *orm_ref)
Remove outstanding file request for the given handle.
Definition: mh5fileorm.c:979
#define PRINTFILE(t, n, d, s)
Definition: mh5fileorm.c:820
void * user_data
Definition: fs_types.h:58
Mheg5 logging and debug printing.
#define SET_ORM_MAGIC(r)
Definition: mh5fileorm.c:129
void * MHEG5GetHybridFileSystemMapping(MHEG5String *reference)
Return mapping from the hybrid file system given path name. The mapping must be released using MHEG5R...
Definition: mh5hfs.c:211
U16BIT service_id
Definition: dvblocator.h:34
#define HybrClear
Definition: mh5fileorm.c:378
File interface functions to DSMCC component.
redirection include
void MHEG5FileOrmReset(MHEG5FileOrmResetMode resetMode)
Reset the ORM module. This function supports two modes:
Definition: mh5fileorm.c:595
U32BIT MHEG5GetTlsCertStoreCount(void)
Return number of TLS certificates in the TLS certificate store.
Definition: mh5tls.c:112
#define MAX_CI_REQUESTS
Definition: mh5fileorm.c:82
struct sOrmGetRequest S_OrmGetRequest
#define CLEAR_ORM_MAGIC(r)
Definition: mh5fileorm.c:130
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
S_OrmPostRequest post
Definition: mh5fileorm.c:279
Definition: mg_png.c:52
P_OrmRequest next
Definition: mh5fileorm.c:257
#define FALSE
Definition: techtype.h:68
Functions relating to TLS certificate store.
The timer module allows the use of timers within the MHEG5 component. These timers can be set by othe...
S_FileSystemAck fsAck
Definition: glue_queue.h:208
void MHEG5ReleaseHybridFileSystemMapping(void *mapping)
Release mapping returned from the hybrid file system. The mapping must be have been returned by a cal...
Definition: mh5hfs.c:270
MHEG5String MHEG5CreateUrl(E_FS_ORIGIN origin, S_STRING path, S_STRING name)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:444
void httpDestroyRequest(HttpRequest_t request)
Destroy an HTTP request.
#define FRP_HASH
Definition: mh5fileorm.h:45
MHEG5Int len
Definition: mh5base.h:84
MHEG5String url
Definition: mh5fileorm.c:266
S_OrmGetRequest get
Definition: mh5fileorm.c:278
MHEG5String MHEG5GetNextReference(MHEG5String *reference, MHEG5MappingIter_t *iter)
Return next reference from mapping iterator.
Definition: mh5hfs.c:301
struct sOrmFuncs S_OrmFuncs
U8BIT * data
Definition: fs_types.h:55
U8BIT BOOLEAN
Definition: techtype.h:99
U32BIT zlen
Definition: dtvstring.h:30
#define TRUE
Definition: techtype.h:69
MHEG5ContentVerification_t
Definition: mh5hash.h:37
MHEG5String responseData
Definition: mh5fileorm.c:252
F_CB_Fail cbFail
Definition: mh5fileorm.c:240
void * MHEG5FileOrmGet(MHEG5String name, U16BIT priority, void *userData, F_CB_Good cbGood, F_CB_Fail cbFail)
Get a file. The file will be loaded and one of the callback functions called when request is resolved...
Definition: mh5fileorm.c:1179
#define ORM_STATE_STRING(r)
Definition: mh5fileorm.c:148
#define FRP_GROUP
Definition: mh5fileorm.h:42
#define WARNING_PRINT(x)
Definition: mh5debug.h:73
FS_HANDLE fs_handle
Definition: fs_types.h:57
E_FS_ORIGIN origin
Definition: mh5fileorm.c:261
struct HttpRequest_tag * HttpRequest_t
#define MIN_HTTP_REPLY_BLOCK
Definition: mh5fileorm.c:86
HttpRequest_t httpCreateGetRequest(U8BIT *url, U8BIT cachePriority, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP GET request.
E_FS_ORIGIN
Definition: mh5gate.h:48
union s_mhg_message::@13 data
F_CB_Post callback
Definition: mh5fileorm.c:249
#define HttpAction
Definition: mh5fileorm.c:379
E_MhegErr DVB_MhegDvbLocatorToIndex(S_DvbLocator *pDvbLocator, S32BIT *pServiceIndex)
Get a DVB implementation dependant service index - an integer greater or equal to 0...
E_FsStatus FG_FileExists(E_FS_ORIGIN origin, const char *fname)
Request file from file group stores.
U32BIT magic
Definition: mh5fileorm.c:259
#define FRP_VERIFY
Definition: mh5fileorm.h:44
#define MHEG5FALSE
Definition: mh5base.h:48
uint32_t U32BIT
Definition: techtype.h:86
#define FRP_CERT
Definition: mh5fileorm.h:46
BOOLEAN MHEG5FileOrmIsReset(MHEG5FileOrmResetMode *resetMode)
Tell whether the ORM module is currently being reset. If it is, the function also returns the current...
Definition: mh5fileorm.c:712
E_FsStatus
Definition: fs_types.h:34
Functions relating to Hybrid file system.
E_MhegErr VT_TimerDestroy(H_Timer timerHandle)
Destroy the specified timer. A callback will not be invoked for this timer after this function return...
Definition: glue_timers.c:324
void MH5GlueAddPostProcessFunc(F_PostProcess func)
Definition: glue_main.c:275
#define CI_ACK_TIMEOUT
Definition: mh5fileorm.c:84
#define MHEG5_ABSOLUTE_PATH_LENGTH
Definition: mh5profile.h:122
#define DEBUG_PRINT(x)
Definition: mh5debug.h:70
#define TRACE(t, x)
Definition: glue_debug.h:118