31 #include <curl/curl.h> 33 #include <openssl/ssl.h> 42 #define HTTP_IDLE_TIMEOUT 200 43 #define MAX_USER_AGENT 256 45 #define CHK_EASY(call) \ 49 if (code != CURLE_OK) \ 51 TRACE(TERROR, ("FAIL %s",#call)) \ 58 #define DBG_ENTRY(x) DBG_PRINTF(" >> %s\n", #x); 59 #define DBG_EXIT(x) DBG_PRINTF(" << %s\n", #x); 87 static CURLM *multi_handle = NULL;
89 static void *ssl_mutex;
92 static U16BIT http_timeout = 30;
93 static char curl_error_buffer[CURL_ERROR_SIZE];
99 static size_t httpWriteCallback(
void *ptr,
size_t size,
100 size_t nmemb,
void *handle);
101 static size_t httpHeaderCallback(
void *ptr,
size_t size,
102 size_t nmemb,
void *handle);
104 static CURLcode httpSslCtxFunction(CURL *curl,
void *sslctx,
void *parm);
119 multi_handle = curl_multi_init();
120 if (multi_handle != NULL)
144 strcpy(http_user_agent, (
char *)user_agent);
167 http_timeout = timeout;
197 *handle = curl_easy_init();
201 if (client_info != NULL)
206 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_URL, (
U8BIT *)url));
207 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_PRIVATE, client_info));
209 if (http_user_agent[0] !=
'\0')
211 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_USERAGENT,
215 curl_error_buffer[0] = 0;
216 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_ERRORBUFFER,
218 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_WRITEFUNCTION,
220 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_WRITEDATA, *handle));
221 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_HEADERFUNCTION,
222 httpHeaderCallback));
223 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_WRITEHEADER, *handle));
225 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_HEADER, 0));
226 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_NOPROGRESS, 1));
227 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_HTTP_VERSION,
228 CURL_HTTP_VERSION_1_1));
230 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_SSL_CTX_FUNCTION,
231 httpSslCtxFunction));
232 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_SSL_CIPHER_LIST,
233 "aRSA:MD5:SHA:eNULL"));
234 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_CAINFO, NULL));
236 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_CONNECTTIMEOUT,
238 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_LOW_SPEED_LIMIT, 32));
239 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_LOW_SPEED_TIME,
245 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_HTTPGET, 1));
248 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_NOBODY, 1));
251 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_POST, 1));
252 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_POSTFIELDS,
""));
253 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_POSTFIELDSIZE, 0));
256 CHK_EASY(curl_easy_setopt(*handle, CURLOPT_HTTPGET, 1));
262 curl_easy_cleanup(*handle);
290 CURLMcode multi_code;
302 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
303 client_info =
private;
304 if (client_info->
headers != NULL)
306 code = curl_easy_setopt(handle, CURLOPT_HTTPHEADER,
310 if (code == CURLE_OK)
313 multi_code = curl_multi_add_handle(multi_handle, handle);
314 if (multi_code == CURLM_OK)
320 TRACE(TERROR,(
"curl_multi_add_handle %d",multi_code))
325 TRACE(TERROR,(
"curl_easy_setopt d",code))
357 code = curl_easy_pause(handle, CURLPAUSE_CONT);
358 if (code == CURLE_OK)
366 TRACE(TERROR,(
"CURL error %d",code))
388 CURLMcode multi_code;
397 multi_code = curl_multi_remove_handle(multi_handle, handle);
398 if (multi_code == CURLM_OK)
433 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
434 client_info =
private;
435 if (client_info->
headers != NULL)
437 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, NULL);
438 curl_slist_free_all(client_info->
headers);
444 curl_easy_cleanup(handle);
476 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
477 client_info =
private;
509 if (handle != NULL && header != NULL)
511 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
512 client_info =
private;
544 if (handle != NULL && postdata != NULL)
546 code = curl_easy_setopt(handle, CURLOPT_POSTFIELDS, postdata);
547 if (code == CURLE_OK)
549 code = curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, -1);
550 if (code == CURLE_OK)
582 if (handle != NULL && range != NULL)
584 CHK_EASY(curl_easy_setopt(handle, CURLOPT_RANGE, range));
615 if (handle != NULL && url != NULL)
617 code = curl_easy_getinfo(handle, CURLINFO_REDIRECT_URL, &redir_url);
618 if (code == CURLE_OK)
620 *url = (
U8BIT *)redir_url;
651 if (cert != NULL && len > 0)
654 pcert = &http_cert_list;
655 while (*pcert != NULL)
657 pcert = &(*pcert)->
next;
664 curr->
x509 = httpParseCertificate(cert, len);
665 if (curr->
x509 != NULL)
701 pcert = &http_cert_list;
702 while (*pcert != NULL)
705 *pcert = (*pcert)->
next;
706 X509_free(curr->
x509);
726 CURLMcode multi_code;
731 struct timeval timeout;
743 multi_code = curl_multi_fdset(multi_handle, &readfds, &writefds,
744 &exceptfds, &max_fd);
745 if (multi_code == CURLM_OK)
751 select(max_fd + 1, &readfds, &writefds, &exceptfds, &timeout);
772 CURLMcode multi_code;
786 multi_code = curl_multi_perform(multi_handle, &running_handles);
789 while (multi_code == CURLM_CALL_MULTI_PERFORM);
791 if (multi_code == CURLM_OK)
795 multi_msg = curl_multi_info_read(multi_handle, &msgs_in_queue);
796 if (multi_msg != NULL)
798 if (multi_msg->msg == CURLMSG_DONE)
800 curl_easy_getinfo(multi_msg->easy_handle,
801 CURLINFO_PRIVATE, &
private);
802 client_info =
private;
803 switch (multi_msg->data.result)
808 case CURLE_PARTIAL_FILE:
811 case CURLE_SSL_CACERT:
814 case CURLE_COULDNT_RESOLVE_PROXY:
815 case CURLE_COULDNT_RESOLVE_HOST:
816 case CURLE_COULDNT_CONNECT:
819 case CURLE_OPERATION_TIMEDOUT:
824 TRACE(TERROR,(
"error buffer=%s",curl_error_buffer));
826 TRACE(TICS, (
"ud=%p status=%u rslt=%u", client_info->
userdata, status, multi_msg->data.result));
831 TRACE(TERROR,(
"multi_msg->msg = %d\n", multi_msg->msg));
835 while (multi_msg != NULL);
841 TRACE(TERROR,(
"curl error %s", curl_multi_strerror(multi_code)));
844 *active_count = running_handles;
860 if (multi_handle != NULL)
862 curl_multi_cleanup(multi_handle);
866 curl_global_cleanup();
883 static size_t httpHeaderCallback(
void *ptr,
size_t size,
884 size_t nmemb,
void *handle)
892 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
893 curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
895 client_info =
private;
896 TRACE(TICS, (
"itm size=%u num=%u ptr=%p", size, nmemb, ptr));
913 static size_t httpWriteCallback(
void *ptr,
size_t size,
914 size_t nmemb,
void *handle)
923 retval = size * nmemb;
925 curl_easy_getinfo(handle, CURLINFO_PRIVATE, &
private);
926 client_info =
private;
927 TRACE(TICS, (
"itm size=%u num=%u ptr=%p", size, nmemb, ptr));
932 retval = CURL_WRITEFUNC_PAUSE;
956 bio = BIO_new_mem_buf(
buffer, length);
959 x509 = d2i_X509_bio(bio, NULL);
979 static CURLcode httpSslCtxFunction(CURL *curl,
void *sslctx,
void *parm)
981 SSL_CTX *ssl_ctx = sslctx;
982 X509_STORE *x509_store;
984 X509_VERIFY_PARAM *param;
993 x509_store = SSL_CTX_get_cert_store(ssl_ctx);
994 if (x509_store != NULL)
999 curr = http_cert_list;
1000 while (curr != NULL)
1002 if (X509_STORE_add_cert(x509_store, curr->
x509) == 0)
1004 TRACE(TERROR,(
"failed to ADD cert"));
1005 rc = CURLE_SSL_CERTPROBLEM;
1014 param = X509_VERIFY_PARAM_new();
1018 tmstruct.tm_sec = date_time.
second;
1019 tmstruct.tm_min = date_time.
minute;
1020 tmstruct.tm_hour = date_time.
hour;
1021 tmstruct.tm_mday = date_time.
day;
1022 tmstruct.tm_mon = date_time.
month - 1;
1023 tmstruct.tm_year = date_time.
year - 1900;
1024 tmstruct.tm_isdst = 0;
1025 current_time = mktime(&tmstruct);
1026 X509_VERIFY_PARAM_set_time(param, current_time);
1027 X509_STORE_set1_param(x509_store, param);
1028 X509_VERIFY_PARAM_free(param);
1036 TRACE(TERROR,(
"failed to GET cert"));
1037 rc = CURLE_SSL_CERTPROBLEM;
1039 TRACE(TICS, (
"rc=%d", rc));
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.
E_MhegErr DVB_MhegGetLocalTime(S_DateTime *pDateAndTime)
Provide the current local time and date, normally from the system real time clock, with any local time conversions (if necessary). The returned time should take into account local timezone and daylight saving settings.
E_HttpErr HP_Process(U16BIT *active_count)
Process HTTP requests. This may cause request callbacks to be called.
void STB_OSTaskDelay(U16BIT timeout)
Delay Task for Specifed Time Period.
E_HttpErr HP_StartRequest(void *handle)
Start an HTTP request.
void STB_MemFree(void *ptr)
Releases previously allocated memory.
void STB_OSDeleteMutex(void *mutex)
Delete a mutex.
E_HttpErr HP_SetRange(void *handle, U8BIT *range)
Set "Range:" header for an HTTP request.
E_HttpErr HP_StopRequest(void *handle)
Stop an HTTP request.
System Memory allocation interface.
E_HttpErr HP_ClearTlsCertificates(void)
Clear TLS certificates.
E_HttpErr HP_GetRedirectUrl(void *handle, U8BIT **url)
Get redirection URL for HTTP request.
struct HttpClientInfo_tag * HttpClientInfo_t
struct curl_slist * headers
E_HttpErr HP_ResumeRequest(void *handle)
Resume an HTTP request.
void STB_OSMutexUnlock(void *mutex)
Unlock a mutex (a.k.a. 'leave', 'signal' or 'release')
void * STB_MemAlloc(U32BIT memSize)
Allocates the specified number of bytes.
struct HttpCertList_tag * HttpCertList_t
struct HttpCertList_tag * next
void * STB_OSCreateMutex(void)
Create a mutex.
E_HttpErr HP_WaitForAction(void)
Wait until there is some activity on one (or more) of the HTTP requests, or until some other conditio...
E_HttpErr HP_SetPostData(void *handle, U8BIT *postdata)
Set POST data for an HTTP request.
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.
E_HttpErr HP_Initialise(void)
Initialise the HTTP interface.
E_HttpErr HP_DestroyRequest(void *handle)
Destroy an HTTP request.
void STB_OSMutexLock(void *mutex)
Lock a mutex (a.k.a. 'enter', 'wait' or 'get').
#define HTTP_IDLE_TIMEOUT
E_HttpErr HP_AddHeader(void *handle, U8BIT *header)
Add HTTP header to HTTP request.
References: [1] UK1 Profile - Digital Terrestrial Television - Requirements for interoperability (The...
E_HttpErr HP_SetUserAgent(U8BIT *user_agent)
Set user agent for HTTP client.
E_HttpErr HP_SetUserData(void *handle, void *userdata)
Set user data associated with an HTTP request.
E_HttpErr HP_AddTlsCertificate(U8BIT *cert, U32BIT len)
Add a certificate for TLS connections.
E_HttpErr HP_Terminate(void)
Terminate the HTTP interface.
Header file - Function prototypes for operating system.