MHEG5  18.9.0
MHEG5 Documentation
http_interface.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2009 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 #if defined(INCLUDE_IC)
26 
27 #include <assert.h>
28 #include <string.h>
29 
30 #include "mh5support.h"
31 #include "http_platform.h"
32 #include "http_interface.h"
33 #include "glue_memory.h"
34 #include "glue_debug.h"
35 
36 #include "dvb_misc.h"
37 #include "stb_os.h"
38 
39 /*---constant definitions for this file--------------------------------------*/
40 
41 #ifndef HTTP_STACK_SIZE
42 #define HTTP_STACK_SIZE 4096
43 #endif
44 
45 #ifndef HTTP_TIMEOUT
46 #define HTTP_TIMEOUT 45
47 #endif
48 
49 #define HTTP_QUEUE_SIZE 512
50 #define HTTP_FAILURE_TIMEOUT 500 /* ms */
51 #define REQUEST_START_TIMEOUT 500 /* ms */
52 #define HTTP_IDLE_TIMEOUT 200 /* ms */
53 #define MAX_RANGE_LEN 255
54 
55 //#define HTTP_DEBUG
56 #ifdef HTTP_DEBUG
57 #define DBG_ENTRY(x) DBG_PRINTF(" >> %s\n", #x);
58 #define DBG_EXIT(x) DBG_PRINTF(" << %s\n", #x);
59 #else
60 #define DBG_ENTRY(x)
61 #define DBG_EXIT(x)
62 #endif
63 
64 #define MAX_USER_AGENT 256
65 
66 
67 /*---local typedef structs for this file-------------------------------------*/
68 
69 typedef enum HttpRequestCmd_tag
70 {
71  HTTP_REQUEST_ADD,
72  HTTP_REQUEST_RESUME,
73  HTTP_REQUEST_REMOVE,
74  HTTP_REQUEST_NONE
75 } HttpRequestCmd_t;
76 
77 struct HttpRequest_tag
78 {
79  struct HttpRequest_tag *next;
80  HttpCallback_t header_cb;
81  HttpCallback_t callback;
82  U32BIT request_id;
83  S32BIT response_code;
84  U8BIT *url;
85  void *userdata;
86  U8BIT *postdata;
87  U32BIT postdata_len;
88  U8BIT range[MAX_RANGE_LEN];
89  BOOLEAN processing;
90  void *handle;
91 };
92 
93 typedef struct HttpTaskCmd_tag
94 {
95  HttpRequest_t request;
96  HttpRequestCmd_t kind;
97 } HttpTaskCmd;
98 
99 enum HttpTaskStatus_t
100 {
101  HTTP_TASK_STOPPED,
102  HTTP_TASK_RUNNING,
103  HTTP_TASK_STOP_REQUEST
104 };
105 
106 
107 /*---local (static) variable declarations for this file----------------------*/
108 /* HTTP task related */
109 static void *http_task_handle = NULL;
110 static enum HttpTaskStatus_t http_task_status = HTTP_TASK_STOPPED;
111 static void *http_task_semaphore = NULL;
112 static void *http_task_mutex = NULL;
113 static void *http_task_queue = NULL;
114 
115 static HttpRequest_t http_request_list = NULL;
116 static U32BIT http_cert_count = 0;
117 static U8BIT http_user_agent[MAX_USER_AGENT + 1] = { 0 };
118 
119 /*---local function definitions----------------------------------------------*/
120 
121 /*---global function definitions---------------------------------------------*/
122 static void httpSetRequestUrl(U8BIT *requrl, U8BIT *url);
123 static void httpSetupCache(HttpRequest_t request, U8BIT cachePriority);
124 static BOOLEAN httpStartTask(U32BIT taskPriority);
125 static void httpStopTask(void);
126 static void httpTaskMain(void *task_arg);
127 static void httpAddRequest(HttpRequest_t request);
128 static void httpContinueRequest(HttpRequest_t request);
129 static void httpRemoveRequest(HttpRequest_t request);
130 static U16BIT httpProcessRequests(void);
131 static BOOLEAN httpIsValidRequest(HttpRequest_t request);
132 
133 #ifdef DEBUG_LIST
134 static void httpPrintRequestList(void);
135 #endif
136 
137 static void httpCookieParse(void *data, U32BIT data_len, char *url);
138 static U8BIT* httpCookieGenerateHeader(U8BIT *url);
139 static void httpCookieAckHeader(U8BIT *header);
140 
141 static HttpCookieManager_t cookie_manager = {
142  httpCookieParse,
143  httpCookieGenerateHeader,
144  httpCookieAckHeader
145 };
146 
147 
154 E_HttpErr httpOpen(U32BIT task_priority)
155 {
156  E_HttpErr err;
157  BOOLEAN success;
158 
160 
161  if (http_task_semaphore != NULL)
162  {
163  err = HTTP_OK;
164  }
165  else
166  {
167  http_task_semaphore = STB_OSCreateSemaphore();
168  if (http_task_semaphore == NULL)
169  {
170  err = HTTP_ERR_INTERNAL;
171  }
172  else
173  {
174  /* Initial value for semaphore is 1, so do wait to decrement value to 0 */
175  STB_OSSemaphoreWait(http_task_semaphore);
176  http_task_mutex = STB_OSCreateMutex();
177  if (http_task_mutex == NULL)
178  {
179  err = HTTP_ERR_INTERNAL;
180  STB_OSDeleteSemaphore(http_task_semaphore);
181  http_task_semaphore = NULL;
182  }
183  else
184  {
185  http_task_queue = STB_OSCreateQueue(sizeof(HttpTaskCmd), HTTP_QUEUE_SIZE);
186  if (http_task_queue == NULL)
187  {
188  err = HTTP_ERR_INTERNAL;
189  STB_OSDeleteMutex(http_task_mutex);
190  http_task_mutex = NULL;
191  STB_OSDeleteSemaphore(http_task_semaphore);
192  http_task_semaphore = NULL;
193  }
194  else
195  {
196  err = HP_Initialise();
197  if (err == HTTP_OK)
198  {
199  TRACE(TFILE,("Set timeout"));
200  HP_SetTimeout(HTTP_TIMEOUT);
201  success = httpStartTask(task_priority);
202  if (!success)
203  {
204  TRACE(TERROR,("Start task failed"));
205  HP_Terminate();
206  STB_OSDestroyQueue(http_task_queue);
207  http_task_queue = NULL;
208  STB_OSDeleteMutex(http_task_mutex);
209  http_task_mutex = NULL;
210  STB_OSDeleteSemaphore(http_task_semaphore);
211  http_task_semaphore = NULL;
212  err = HTTP_ERR_INTERNAL;
213  }
214  }
215  else
216  {
217  TRACE(TERROR,("Init failed err=%d",err));
218  }
219  }
220  }
221  }
222  }
223 
225 
226  return err;
227 }
228 
235 {
236  if (manager != NULL)
237  {
238  cookie_manager = *manager;
239  }
240  else
241  {
242  /* Reset to defaults */
243  cookie_manager.parse = httpCookieParse;
244  cookie_manager.generate_header = httpCookieGenerateHeader;
245  cookie_manager.ack_header = httpCookieAckHeader;
246  }
247 }
248 
254 void httpSetUserAgent(U8BIT *user_agent)
255 {
256  size_t len;
257 
258  len = strlen((char *)user_agent);
259  if (len > MAX_USER_AGENT)
260  {
261  len = MAX_USER_AGENT;
262  }
263  memcpy(http_user_agent, user_agent, len);
264  http_user_agent[len] = '\0';
265  HP_SetUserAgent(http_user_agent);
266 }
267 
272 void httpClearTlsCertStore(void)
273 {
275 
277  http_cert_count = 0;
278 
280 }
281 
286 void httpAddTlsCertToStore(U8BIT *certData, U32BIT certLen)
287 {
288  E_HttpErr err;
289 
291 
292  err = HP_AddTlsCertificate(certData, certLen);
293  if (err == HTTP_OK)
294  {
295  http_cert_count++;
296  }
297 
299 }
300 
306 {
308 
310 
311  return http_cert_count;
312 }
313 
326 HttpRequest_t httpCreateGetRequest(U8BIT *url, U8BIT cachePriority,
327  HttpCallback_t callback,
328  U32BIT request_id, void *userdata)
329 {
330  HttpRequest_t request;
331  U8BIT *header;
332 
334 
335  request = STB_MemAlloc(sizeof *request);
336  if (request == NULL)
337  {
338  TRACE(TERROR, ("Malloc failed"));
339  }
340  else
341  {
342  request->url = STB_MemAlloc(strlen((char *)url) + 1);
343  if (request->url != NULL)
344  {
345  httpSetRequestUrl(request->url, url);
346 
347  request->next = NULL;
348  request->header_cb = NULL;
349  request->callback = callback;
350  request->request_id = request_id;
351  request->response_code = 0;
352  request->userdata = userdata;
353  request->postdata = NULL;
354  request->postdata_len = 0;
355  request->processing = FALSE;
356 
357  HP_CreateRequest(request->url, HTTP_REQUEST_GET, &request->handle);
358  if (request->handle != NULL)
359  {
360  TRACE(TFILE, ("HP_CreateRequest %p returned=%p URL=%s", request, request->handle, request->url));
361  HP_SetUserData(request->handle, request);
362 
363  header = cookie_manager.generate_header((U8BIT *)request->url);
364  if (header != NULL)
365  {
366  HP_AddHeader(request->handle, header);
367  cookie_manager.ack_header(header);
368  }
369 
370  httpSetupCache(request, cachePriority);
371  }
372  else
373  {
374  TRACE(TERROR, ("HP_CreateRequest failed"));
375  STB_MemFree(request);
376  request = NULL;
377  }
378  }
379  else
380  {
381  STB_MemFree(request);
382  request = NULL;
383  }
384  }
385 
387 
388  return request;
389 }
390 
401  U32BIT request_id, void *userdata)
402 {
403  HttpRequest_t request;
404  U8BIT *header;
405 
407 
408  request = STB_MemAlloc(sizeof *request);
409  if (request != NULL)
410  {
411  request->url = STB_MemAlloc(strlen((char *)url) + 1);
412  if (request->url != NULL)
413  {
414  httpSetRequestUrl(request->url, url);
415 
416  request->next = NULL;
417  request->header_cb = callback;
418  request->callback = callback;
419  request->request_id = request_id;
420  request->response_code = 0;
421  request->userdata = userdata;
422  request->postdata = NULL;
423  request->postdata_len = 0;
424  request->processing = FALSE;
425 
426  HP_CreateRequest(request->url, HTTP_REQUEST_HEAD, &request->handle);
427  if (request->handle != NULL)
428  {
429  TRACE(TFILE, ("HP_CreateRequest %p returned=%p URL=%s", request, request->handle,request->url));
430  HP_SetUserData(request->handle, request);
431 
432  header = cookie_manager.generate_header((U8BIT *)request->url);
433  if (header != NULL)
434  {
435  HP_AddHeader(request->handle, header);
436  cookie_manager.ack_header(header);
437  }
438  }
439  else
440  {
441  TRACE(TERROR, ("HP_CreateRequest failed"));
442  STB_MemFree(request);
443  request = NULL;
444  }
445  }
446  else
447  {
448  TRACE(TERROR, ("memory fail"));
449  STB_MemFree(request);
450  request = NULL;
451  }
452  }
453 
455 
456  return request;
457 }
458 
471  HttpCallback_t callback,
472  U32BIT request_id, void *userdata)
473 {
474  HttpRequest_t request;
475  U8BIT *header;
476  BOOLEAN success;
477  E_HttpErr err;
478 
480 
481  request = STB_MemAlloc(sizeof *request);
482  if (request != NULL)
483  {
484  request->url = STB_MemAlloc(strlen((char *)url) + 1);
485  if (request->url != NULL)
486  {
487  httpSetRequestUrl(request->url, url);
488 
489  request->next = NULL;
490  request->header_cb = NULL;
491  request->callback = callback;
492  request->request_id = request_id;
493  request->response_code = 0;
494  request->userdata = userdata;
495  request->processing = FALSE;
496 
497  if (data != NULL)
498  {
499  request->postdata_len = strlen((char *)data);
500  request->postdata = STR_DataAlloc(request->postdata_len);
501  if (request->postdata != NULL)
502  {
503  memcpy(request->postdata, data, request->postdata_len);
504  }
505  else
506  {
507  request->postdata_len = 0;
508  }
509  }
510  else
511  {
512  request->postdata = NULL;
513  request->postdata_len = 0;
514  }
515 
516  HP_CreateRequest(request->url, HTTP_REQUEST_POST, &request->handle);
517  if (request->handle != NULL)
518  {
519  TRACE(TFILE, ("HP_CreateRequest %p returned=%p", request, request->handle));
520 
521  success = TRUE;
522  HP_SetUserData(request->handle, request);
523 
524  header = cookie_manager.generate_header((U8BIT *)request->url);
525  if (header != NULL)
526  {
527  HP_AddHeader(request->handle, header);
528  cookie_manager.ack_header(header);
529  }
530 
531  if (request->postdata != NULL)
532  {
533  err = HP_SetPostData(request->handle, request->postdata);
534  if (err != HTTP_OK)
535  {
536  TRACE(TERROR, ("HP_SetPostData failed %p",err));
537  success = FALSE;
538  }
539  }
540 
541  if (!success)
542  {
543  TRACE(TFILE, ("Destroying Request hdl=%p", request->handle));
544  HP_DestroyRequest(request->handle);
545  if (request->postdata != NULL)
546  {
547  STR_DataFree(request->postdata, request->postdata_len);
548  }
549  STB_MemFree(request);
550  request = NULL;
551  }
552  }
553  else
554  {
555  TRACE(TERROR, ("HP_CreateRequest failed"));
556  STB_MemFree(request);
557  request = NULL;
558  }
559  }
560  else
561  {
562  STB_MemFree(request);
563  request = NULL;
564  }
565  }
566 
568 
569  return request;
570 }
571 
584  HttpCallback_t header_callback,
585  HttpCallback_t callback,
586  U32BIT request_id, void *userdata)
587 {
588  HttpRequest_t request;
589  U8BIT *header;
590 
592 
593  request = STB_MemAlloc(sizeof *request);
594  if (request != NULL)
595  {
596  request->url = STB_MemAlloc(strlen((char *)url) + 1);
597  if (request->url != NULL)
598  {
599  httpSetRequestUrl(request->url, url);
600 
601  request->next = NULL;
602  request->header_cb = header_callback;
603  request->callback = callback;
604  request->request_id = request_id;
605  request->response_code = 0;
606  request->userdata = userdata;
607  request->postdata = NULL;
608  request->postdata_len = 0;
609  request->processing = FALSE;
610 
611  HP_CreateRequest(request->url, HTTP_REQUEST_STREAM, &request->handle);
612  if (request->handle != NULL)
613  {
614  TRACE(TICS, ("HP_CreateRequest %p returned=%p URL=%s", request, request->handle, request->url));
615  HP_SetUserData(request->handle, request);
616 
617  header = cookie_manager.generate_header((U8BIT *)request->url);
618  if (header != NULL)
619  {
620  HP_AddHeader(request->handle, header);
621  cookie_manager.ack_header(header);
622  }
623 
624  request->range[0] = '\0';
625  if (range != NULL)
626  {
627  strcpy((char *)request->range, (char *)range);
628  HP_SetRange(request->handle, request->range);
629  }
630  }
631  else
632  {
633  TRACE(TERROR, ("HP_CreateRequest failed"));
634  STB_MemFree(request);
635  request = NULL;
636  }
637  }
638  else
639  {
640  STB_MemFree(request);
641  request = NULL;
642  }
643  }
644 
646 
647  return request;
648 }
649 
656 void httpStartRequest(HttpRequest_t request)
657 {
658  BOOLEAN success;
659  HttpTaskCmd cmd;
660 
662 
663  /* Add request to requests pool */
664  cmd.request = request;
665  cmd.kind = HTTP_REQUEST_ADD;
666 
667  TRACE(TICS, ("%p hdl=%p", request, request->handle));
668  /* Send request to HTTP task */
669  do
670  {
671  success = STB_OSWriteQueue(http_task_queue, &cmd, sizeof cmd,
672  REQUEST_START_TIMEOUT);
673  if (!success)
674  {
675  TRACE(TERROR,("Cannot add to queue, retrying"));
676  }
677  }
678  while (!success);
679 
681 }
682 
691 void httpResumeRequest(HttpRequest_t request)
692 {
693  BOOLEAN success;
694  HttpTaskCmd cmd;
695 
697 
698  /* Add request to requests pool */
699  cmd.request = request;
700  cmd.kind = HTTP_REQUEST_RESUME;
701 
702  TRACE(TFILE, ("%p hdl=%p", request, request->handle));
703  /* Send request to HTTP task */
704  do
705  {
706  success = STB_OSWriteQueue(http_task_queue, &cmd, sizeof cmd,
707  REQUEST_START_TIMEOUT);
708  if (!success)
709  {
710  TRACE(TERROR,("Cannot resume to queue, retrying"));
711  }
712  }
713  while (!success);
714 
716 }
717 
725 {
726  U8BIT *url;
727 
729 
730  HP_GetRedirectUrl(request->handle, &url);
731 
733 
734  return url;
735 }
736 
743 void httpStopRequest(HttpRequest_t request)
744 {
745  BOOLEAN success;
746  HttpTaskCmd cmd;
747 
749 
750  /* Remove request from requests pool */
751  cmd.request = request;
752  cmd.kind = HTTP_REQUEST_REMOVE;
753 
754  TRACE(TICS, ("%p hdl=%p", request, request->handle));
755  /* Send request to HTTP task */
756  do
757  {
758  success = STB_OSWriteQueue(http_task_queue, &cmd, sizeof cmd,
759  REQUEST_START_TIMEOUT);
760  }
761  while (!success);
762 
763  /* Wait for request to be stopped */
764  STB_OSSemaphoreWait(http_task_semaphore);
765 
766  TRACE(TICS, ("Stopped Request %p", request));
767 
769 }
770 
775 void httpDestroyRequest(HttpRequest_t request)
776 {
778 
779  assert(request != NULL);
780  assert(request->handle != NULL);
781 
782  TRACE(TICS, ("Destroying Request hdl=%p", request->handle));
783  HP_DestroyRequest(request->handle);
784  if (request->postdata != NULL)
785  {
786  STR_DataFree(request->postdata, request->postdata_len);
787  }
788  STB_MemFree(request->url);
789  STB_MemFree(request);
790 
792 }
793 
798 void httpClose(void)
799 {
801 
802  httpStopTask();
803 
804  /* curl does not work too well with 'cleanup'/'init' cycle
805  * So - it can be disabled here
806  */
807 #ifndef DISABLE_HTTP_CLOSEDOWN
808 
809  STB_OSDestroyQueue(http_task_queue);
810  STB_OSDeleteMutex(http_task_mutex);
811  STB_OSDeleteSemaphore(http_task_semaphore);
812  http_task_semaphore = NULL;
813 
814  HP_Terminate();
815 
816 #endif
817 
819 }
820 
827 static void httpSetRequestUrl(U8BIT *requrl, U8BIT *url)
828 {
829  static char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
830  static char uppercase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
831  char *p, *sp;
832  int c, idx;
833 
834  DBG_ENTRY(httpSetRequestUrl);
835 
836  strcpy((char *)requrl, (char *)url);
837 
838  /* The URL should already have the correct format, so we can assume
839  * http(s)://<hostname>/<rest>
840  */
841  p = strstr((char *)requrl, "://");
842  if (p != NULL)
843  {
844  for (p += 3; *p != '/' && *p != '\0'; p++)
845  {
846  c = *p;
847  /* NOTE: slower but more portable than "(c >= 'A' && c <= 'Z')" */
848  sp = strchr(uppercase, c);
849  if (sp != NULL)
850  {
851  idx = sp - uppercase;
852  *p = lowercase[idx];
853  }
854  }
855  }
856 
857  DBG_EXIT(httpSetRequestUrl);
858 }
859 
868 static void httpSetupCache(HttpRequest_t request, U8BIT cachePriority)
869 {
870  if (cachePriority == 0)
871  {
872  /* No caching */
873  HP_AddHeader(request->handle, (U8BIT *)"Cache-Control: no-cache, no-transform");
874  HP_AddHeader(request->handle, (U8BIT *)"Pragma: no-cache");
875  }
876  else if (cachePriority % 2 == 0)
877  {
878  /* From cache (as much as possible) */
879  HP_AddHeader(request->handle, (U8BIT *)"Cache-Control: max-stale, no-transform");
880  }
881  else
882  {
883  /* Transparent caching */
884  HP_AddHeader(request->handle, (U8BIT *)"Cache-Control: no-transform");
885  }
886 }
887 
892 static BOOLEAN httpStartTask(U32BIT taskPriority)
893 {
894  BOOLEAN success;
895 
896  DBG_ENTRY(httpStartTask);
897 
898  http_task_handle = STB_OSCreateTask(httpTaskMain, NULL, HTTP_STACK_SIZE,
899  (U8BIT)taskPriority, (U8BIT *)"HTTP");
900  if (http_task_handle != NULL)
901  {
902  STB_OSSemaphoreWait(http_task_semaphore);
903  success = TRUE;
904  }
905 
906  DBG_EXIT(httpStartTask);
907 
908  return success;
909 }
910 
915 static void httpStopTask(void)
916 {
917  DBG_ENTRY(httpStopTask);
918 
919  if (http_task_status == HTTP_TASK_RUNNING)
920  {
921  http_task_status = HTTP_TASK_STOP_REQUEST;
922  STB_OSSemaphoreWait(http_task_semaphore);
923 
924  assert(http_task_status == HTTP_TASK_STOPPED);
925  }
926 
927  DBG_EXIT(httpStopTask);
928 }
929 
934 static void httpTaskMain(void *task_arg)
935 {
936  U16BIT count;
937  BOOLEAN success;
938  HttpTaskCmd cmd;
939 
940  DBG_ENTRY(httpTaskMain);
941 
942  http_task_status = HTTP_TASK_RUNNING;
943  STB_OSSemaphoreSignal(http_task_semaphore);
944 
945  while (http_task_status == HTTP_TASK_RUNNING)
946  {
947  count = httpProcessRequests();
948  if (count == 0)
949  {
950  success = STB_OSReadQueue(http_task_queue, &cmd, sizeof cmd,
952  STB_OSTaskDelay(1);
953  }
954  else
955  {
956  success = FALSE;
957  }
958 
959  while (success || count > 0)
960  {
961  if (success)
962  {
963  /* New HTTP request */
964  switch (cmd.kind)
965  {
966  case HTTP_REQUEST_ADD:
967  httpAddRequest(cmd.request);
968  break;
969  case HTTP_REQUEST_RESUME:
970  httpContinueRequest(cmd.request);
971  break;
972  case HTTP_REQUEST_REMOVE:
973  httpRemoveRequest(cmd.request);
974  /* Stay in idle mode */
975  break;
976  case HTTP_REQUEST_NONE:
977  /* Requests in the queue should not have NONE command */
978  assert(0);
979  break;
980  }
981  }
982 
983  count = httpProcessRequests();
984  success = STB_OSReadQueue(http_task_queue, &cmd, sizeof cmd, 0);
985  STB_OSTaskDelay(1);
986  }
987  }
988 
989  if (http_task_status == HTTP_TASK_STOP_REQUEST)
990  {
991  http_task_status = HTTP_TASK_STOPPED;
992  STB_OSSemaphoreSignal(http_task_semaphore);
993  }
994 
995  STB_OSDestroyTask(http_task_handle);
996  DBG_EXIT(httpTaskMain);
997 }
998 
1004 static void httpAddRequest(HttpRequest_t request)
1005 {
1006  U16BIT dummy;
1007  HttpRequest_t *p_request;
1008  E_HttpErr err;
1009 
1010  DBG_ENTRY(httpAddRequest);
1011 
1012 #ifdef DEBUG_LIST
1013  httpPrintRequestList();
1014 #endif
1015  if (request == NULL)
1016  {
1017  TRACE(TERROR, ("request is NULL!"));
1018  }
1019  else
1020  {
1021  TRACE(TICS, ("Start request hdl=%p", request->handle));
1022  err = HP_StartRequest(request->handle);
1023  if (err == HTTP_OK)
1024  {
1025  /* Append request to request list */
1026  p_request = &http_request_list;
1027  while (*p_request != NULL)
1028  {
1029  p_request = &(*p_request)->next;
1030  }
1031  *p_request = request;
1032 
1033  /* Start the transfer */
1034  HP_Process(&dummy);
1035  }
1036  else
1037  {
1038  TRACE(TERROR, ("HP_StartRequest failed %d",err));
1039  }
1040  #ifdef DEBUG_LIST
1041  httpPrintRequestList();
1042  #endif
1043  }
1044  DBG_EXIT(httpAddRequest);
1045 }
1046 
1052 static void httpContinueRequest(HttpRequest_t request)
1053 {
1054  DBG_ENTRY(httpContinueRequest);
1055 
1056  if (httpIsValidRequest(request))
1057  {
1058  if (!request->processing)
1059  {
1060  TRACE(TICS, ("Resuming request hdl=%p", request->handle));
1061  HP_ResumeRequest(request->handle);
1062  }
1063  else
1064  {
1065  TRACE(TICS, ("Resume not needed hdl=%p", request->handle));
1066  }
1067  }
1068 
1069  DBG_EXIT(httpContinueRequest);
1070 }
1071 
1077 static void httpRemoveRequest(HttpRequest_t request)
1078 {
1079  HttpRequest_t *p_request;
1080  E_HttpErr err;
1081 
1082  DBG_ENTRY(httpRemoveRequest);
1083 
1084 #ifdef DEBUG_LIST
1085  httpPrintRequestList();
1086 #endif
1087 
1088  if (!httpIsValidRequest(request))
1089  {
1090  TRACE(TERROR,("request %p was not found", request))
1091  }
1092  else
1093  {
1094  TRACE(TICS, ("Stop request %p hdl=%p", request, request->handle));
1095  err = HP_StopRequest(request->handle);
1096  if (err != HTTP_OK)
1097  {
1098  TRACE(TERROR,("HP_StopRequest for request %p failed err=%d - removing anyway", request, err))
1099  /* TODO: can't remove request? */
1100  }
1101 
1102  /* Remove request from request list */
1103  p_request = &http_request_list;
1104  while (*p_request != NULL)
1105  {
1106  if (*p_request == request)
1107  {
1108  *p_request = request->next;
1109  request->next = NULL;
1110  break;
1111  }
1112  p_request = &(*p_request)->next;
1113  }
1114  }
1115 #ifdef DEBUG_LIST
1116  httpPrintRequestList();
1117 #endif
1118 
1119  /* Signal semaphore even if couldn't remove the request, otherwise
1120  * the caller will wait forever.
1121  */
1122  STB_OSSemaphoreSignal(http_task_semaphore);
1123 
1124  DBG_EXIT(httpRemoveRequest);
1125 }
1126 
1131 static U16BIT httpProcessRequests(void)
1132 {
1133  U16BIT running_handles;
1134 
1135  DBG_ENTRY(httpProcessRequests);
1136 
1137  HP_WaitForAction();
1138  HP_Process(&running_handles);
1139 
1140  DBG_EXIT(httpProcessRequests);
1141 
1142  return running_handles;
1143 }
1144 
1154 void HP_HeaderCallback(void *userdata, S32BIT code, U8BIT *data, U32BIT len)
1155 {
1156  HttpRequest_t request;
1157  HttpResponse_t response;
1158 
1160 
1161  request = userdata;
1162 
1163  request->response_code = code;
1164  cookie_manager.parse(data, len, (char *)request->url);
1165 
1166  if (request->header_cb != NULL && data != NULL && len > 0)
1167  {
1168  response.status = HTTP_STATUS_WAIT;
1169  response.code = code;
1170  response.data = data;
1171  response.data_len = len;
1172  request->header_cb(request->userdata, request->request_id, &response);
1173  }
1174 
1176 }
1177 
1191 BOOLEAN HP_ContentCallback(void *userdata, U8BIT *data, U32BIT len)
1192 {
1193  HttpRequest_t request;
1194  HttpResponse_t response;
1195  BOOLEAN processed = TRUE;
1196 
1198 
1199  request = userdata;
1200  if (request->callback != NULL)
1201  {
1202  response.status = HTTP_STATUS_WAIT;
1203  response.code = 0;
1204  response.data = data;
1205  response.data_len = len;
1206  processed = request->callback(request->userdata, request->request_id,
1207  &response);
1208  request->processing = processed;
1209  }
1210 
1212 
1213  return processed;
1214 }
1215 
1223 void HP_EndCallback(void *userdata, E_HttpStatus status)
1224 {
1225  HttpRequest_t request;
1226  HttpResponse_t response;
1227 
1229 
1230  request = userdata;
1231  if (request->callback != NULL)
1232  {
1233  response.status = status;
1234  response.code = request->response_code;
1235  response.data = NULL;
1236  response.data_len = 0;
1237  request->callback(request->userdata, request->request_id, &response);
1238  }
1239 
1241 }
1242 
1251 static BOOLEAN httpIsValidRequest(HttpRequest_t request)
1252 {
1253  HttpRequest_t current;
1254  BOOLEAN valid;
1255 
1256  valid = FALSE;
1257 
1258  current = http_request_list;
1259  while (current != NULL)
1260  {
1261  if (current == request)
1262  {
1263  valid = TRUE;
1264  break;
1265  }
1266  current = current->next;
1267  }
1268 
1269  return valid;
1270 }
1271 
1272 #ifdef DEBUG_LIST
1273 
1277 static void httpPrintRequestList(void)
1278 {
1279  HttpRequest_t request;
1280 
1281  request = http_request_list;
1282  while (request != NULL)
1283  {
1284  DBG_PRINTF("%p -> ", request); fflush(stdout);
1285  request = request->next;
1286  }
1287  DBG_PRINTF("||\n"); fflush(stdout);
1288 }
1289 
1290 #endif /* DEBUG_LIST */
1291 
1299 static void httpCookieParse(void *data, U32BIT data_len, char *url)
1300 {
1301  /* do nothing */
1302 }
1303 
1309 static U8BIT* httpCookieGenerateHeader(U8BIT *url)
1310 {
1311  return NULL;
1312 }
1313 
1319 static void httpCookieAckHeader(U8BIT *header)
1320 {
1321  /* do nothing */
1322 }
1323 
1324 #endif /*INCLUDE_IC*/
void STB_OSSemaphoreWait(void *semaphore)
Wait on Semaphore Indefinity or Until Released.
E_HttpErr HP_Terminate(void)
Terminate the HTTP interface.
E_HttpErr HP_ResumeRequest(void *handle)
Resume an HTTP request.
E_HttpErr HP_Process(U16BIT *active_count)
Process HTTP requests. This may cause request callbacks to be called.
void httpSetCookieManager(HttpCookieManager_t *manager)
Set cookie manager for HTTP connections.
E_HttpErr HP_DestroyRequest(void *handle)
Destroy an HTTP request.
void httpStartRequest(HttpRequest_t request)
Start an HTTP request. Everything related to the request is passed through the callback that was regi...
Manages the interface between HTTP component and platform.
Manages the interface between MHEG5 Engine and the HTTP component.
E_HttpStatus
Definition: httptype.h:36
#define DBG_PRINTF(...)
Definition: glue_debug.h:127
const char * data
Definition: mh5gate.c:56
#define DBG_EXIT(x)
Definition: curlInterface.c:62
void STB_OSTaskDelay(U16BIT timeout)
Delay Task for Specifed Time Period.
E_HttpStatus status
E_HttpErr HP_Initialise(void)
Initialise the HTTP interface.
void STB_MemFree(void *ptr)
Releases previously allocated memory.
Debug tracing.
void STB_OSDeleteMutex(void *mutex)
Delete a mutex.
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
E_HttpErr HP_SetUserAgent(U8BIT *user_agent)
Set user agent for HTTP client.
E_HttpErr httpOpen(U32BIT task_priority)
Open the HTTP interface.
E_HttpErr HP_StopRequest(void *handle)
Stop an HTTP request.
E_HttpErr
Definition: httptype.h:29
E_HttpErr HP_GetRedirectUrl(void *handle, U8BIT **url)
Get redirection URL for HTTP request.
E_HttpErr HP_AddHeader(void *handle, U8BIT *header)
Add HTTP header to HTTP request.
uint8_t U8BIT
Definition: techtype.h:82
E_HttpErr HP_SetPostData(void *handle, U8BIT *postdata)
Set POST data for an HTTP request.
BOOLEAN STB_OSDestroyQueue(void *queue)
Destroy Queue.
BOOLEAN STB_OSWriteQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Write a message to the queue.
Memory functions.
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)...
E_HttpErr HP_CreateRequest(U8BIT *url, E_HttpRequestType type, void **handle)
Create an HTTP request. The URL is provided, and is guaranteed to be either "http://..." or "https://..." The request type is also provided. Streaming request is the same as a GET request, except that a "Range:" header is also allowed for it.
#define MAX_USER_AGENT
Definition: mh5support.c:51
void * STB_OSCreateSemaphore(void)
Create a Binary Semaphore. That is maximum value of 1. The initial value should be 1...
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.
void * STB_OSCreateQueue(U16BIT msg_size, U16BIT msg_max)
Create Queue of given number of messages and size of message.
E_HttpErr HP_StartRequest(void *handle)
Start an HTTP request.
void * STB_OSCreateMutex(void)
Create a mutex.
BOOLEAN STB_OSReadQueue(void *queue, void *msg, U16BIT msg_size, U16BIT timeout)
Read a message from a queue.
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
E_HttpErr HP_ClearTlsCertificates(void)
Clear TLS certificates.
int32_t S32BIT
Definition: techtype.h:87
E_HttpErr HP_SetUserData(void *handle, void *userdata)
Set user data associated with an HTTP request.
uint16_t U16BIT
Definition: techtype.h:84
void httpClearTlsCertStore(void)
Clear TLS certificate store.
E_HttpErr HP_WaitForAction(void)
Wait until there is some activity on one (or more) of the HTTP requests, or until some other conditio...
#define DBG_ENTRY(x)
Definition: curlInterface.c:61
BOOLEAN HP_ContentCallback(void *userdata, U8BIT *data, U32BIT len)
Callback for HTTP content data. This function is called by the HTTP client. The callback must return ...
void httpResumeRequest(HttpRequest_t request)
Resume an HTTP request. A request can be paused by returning FALSE from the content callback to tell ...
#define FALSE
Definition: techtype.h:68
void HP_HeaderCallback(void *userdata, S32BIT response_code, U8BIT *data, U32BIT len)
Callback for HTTP header data. This function is called by the HTTP client.
E_HttpErr HP_SetRange(void *handle, U8BIT *range)
Set "Range:" header for an HTTP request.
#define HTTP_IDLE_TIMEOUT
Definition: curlInterface.c:42
void httpDestroyRequest(HttpRequest_t request)
Destroy an HTTP request.
void httpSetUserAgent(U8BIT *user_agent)
Set User Agent for HTTP connections.
void httpClose(void)
Close the HTTP interface.
U8BIT BOOLEAN
Definition: techtype.h:99
#define TRUE
Definition: techtype.h:69
void httpAddTlsCertToStore(U8BIT *certData, U32BIT certLen)
Add TLS certificate to store.
HttpRequest_t httpCreateStreamRequest(U8BIT *url, U8BIT *range, HttpCallback_t header_callback, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP request for stream media.
References: [1] UK1 Profile - Digital Terrestrial Television - Requirements for interoperability (The...
void * STB_OSCreateTask(void(*function)(void *), void *param, U32BIT stack, U8BIT priority, U8BIT *name)
Create a New Task to the calling process. Upon success, the created task runs on its own stack...
struct HttpRequest_tag * HttpRequest_t
U32BIT httpGetTlsCertStoreCount(void)
Return number of TLS certificate in the certificate store.
HttpRequest_t httpCreateGetRequest(U8BIT *url, U8BIT cachePriority, HttpCallback_t callback, U32BIT request_id, void *userdata)
Create an HTTP GET request.
BOOLEAN(* HttpCallback_t)(void *userdata, U32BIT request_id, HttpResponse_t *response)
E_HttpErr HP_SetTimeout(U16BIT timeout)
Set timeout (in seconds) for HTTP requests. The timeout applies to connections (i.e. the time it takes to connect to the server) as well as response time (i.e the time it takes to download the content). Between sending the request and receiving the first byte of the the response there is no timeout.
uint32_t U32BIT
Definition: techtype.h:86
void HP_EndCallback(void *userdata, E_HttpStatus status)
Callback for HTTP request end. This function is called by the HTTP client.
Engine support utility functions for MHEG5.
void STB_OSDestroyTask(void *task)
Delete Task must be called upon termination of each task as it frees all OS specific resources alloca...
E_HttpErr HP_AddTlsCertificate(U8BIT *cert, U32BIT len)
Add a certificate for TLS connections.
void STB_OSDeleteSemaphore(void *semaphore)
Delete a Semaphore.
void STB_OSSemaphoreSignal(void *semaphore)
Signal a Semaphore to Release it by decrementing its counter.
#define TRACE(t, x)
Definition: glue_debug.h:118
Header file - Function prototypes for operating system.