http_processor.c
Go to the documentation of this file.
1 /*!**********************************************************************
2  *
3  * @copyright Copyright (C) 2016 Siemens Aktiengesellschaft.\n
4  * All rights reserved.
5  *
6  *************************************************************************
7  *
8  * @file http_processor.c
9  * @date Jul 19, 2016
10  * @brief HTTP processor module implementation file.
11  *
12  ************************************************************************/
13 
14 #include "http_processor.h"
15 #include "log_util.h"
16 #include "memory.h"
17 #include "http_definitions.h"
18 #include "json.h"
19 #include "json_util.h"
20 #include "list.h"
21 #include "data_types.h"
22 #include "time_series.h"
23 #include "event_list.h"
24 #include "file.h"
25 #include "custom_data.h"
26 #include "stream_data.h"
28 #include "definitions.h"
29 #include "jwt.h"
30 #include "storage.h"
31 #include "security.h"
32 #include "http_request.h"
33 #include "random.h"
34 #include "file_util.h"
35 #include "mcl/mcl_common.h"
36 #include "time_util.h"
37 
38 #define SERVER_NONCE "server_nonce"
39 #define SERVER_PROOF "server_proof"
40 
41 #define JSON_NAME_CLIENT_ID "client_id"
42 #define JSON_NAME_TOKEN_ENDPOINT_AUTH_METHOD "token_endpoint_auth_method"
43 #define JSON_NAME_GRANT_TYPES "grant_types"
44 #define JSON_NAME_CLIENT_SECRET "client_secret"
45 #define JSON_NAME_CLIENT_SECRET_EXPIRES_AT "client_secret_expires_at"
46 #define JSON_NAME_REGISTRATION_ACCESS_TOKEN "registration_access_token"
47 #define JSON_NAME_REGISTRATION_CLIENT_URI "registration_client_uri"
48 #define JSON_NAME_JWKS "jwks"
49 #define JSON_NAME_KEYS "keys"
50 #define JSON_NAME_E "e"
51 #define JSON_NAME_N "n"
52 #define JSON_NAME_KTY "kty"
53 #define JSON_NAME_KID "kid"
54 #define JSON_NAME_ACCESS_TOKEN "access_token"
55 
56 #define REGISTER_URI_PATH "/register"
57 #define ACCESS_TOKEN_URI_PATH "/token"
58 
59 // TODO : Max count is TBD :
60 #define MAX_STREAM_CALLBACK_CALL_COUNT 10
61 
62 #define MAX_RANGE_HEADER_LENGTH (100)
63 #define MAX_TOP_EVENT_PARAMETER_LENGTH (50)
64 #define EVENT_REQUEST_LIMIT (100)
65 
66 #define CORRELATION_ID_BYTE_LENGTH 16
67 
71 typedef enum E_ENDPOINT_TYPE
72 {
77 
81 typedef enum E_ENDPOINT_URI
82 {
91 
92 // This is the array for endpoints.
94 {
95  STRING_CONSTANT("api/mindconnect/v3/exchange"),
96  STRING_CONSTANT("api/mindconnect/v3/files"),
97  STRING_CONSTANT("api/mindconnect/v3/events"),
98  STRING_CONSTANT("api/mindconnect/v3/events/acknowledge"),
99  STRING_CONSTANT("api/agentmanagement/v3/oauth/token"),
100  STRING_CONSTANT("api/agentmanagement/v3/register")
101 };
102 
103 // This function processes the HTTP response to an onboarding or key rotation request for shared secret security profile.
105 
106 // This function processes the HTTP response to an onboarding or key rotation request for shared RSA 3072 security profile.
108 
109 // This function concatenates host and endpoint to form URI.
111 
112 #if MCL_FILE_DOWNLOAD_ENABLED
113 // This function extracts file name from Content Disposition header
114 static E_MCL_ERROR_CODE _get_file_name(char *header, string_t **file_name);
115 
116 // Adds range header to HTTP request
117 static E_MCL_ERROR_CODE _add_range_header(http_request_t *request, mcl_size_t start_byte, mcl_size_t end_byte);
118 
119 // Adds actual range values to file
120 static E_MCL_ERROR_CODE _add_actual_range_to_file(http_response_t *response, file_t *file);
121 #endif
122 
123 // This function fills an http request with the provided store as much as it can.
125 
126 // Used for preperation of store data. This means the meta and payload strings preperation from their respective structed objects and setting the state of the data to PREPARED:
128 
129 // This function adds the provided store data to the request. Gets called by _exchange_fill_http_request:
131 
132 // This function adds the provided store data to the request using stream mechanism. Gets called by _exchange_fill_http_request:
134 
135 // This is http response evaluation function. Also updates the store data states based on response status.
136 static E_MCL_ERROR_CODE _exchange_evaluate_response(store_t *store, E_MCL_ERROR_CODE send_result, http_response_t *response, void **reserved, string_t *correlation_id);
137 
138 // This function updates the state's of the data in the store based on the send operation result. If the send operation is failed data needs to be written again so its write counters reset.
139 static E_MCL_ERROR_CODE _exchange_update_store_state(store_t *store, mcl_bool_t send_operation_successful);
140 
141 // This function is for updateing one single store data based on the send operation result. Called by _exchange_update_store_state:
142 static E_MCL_ERROR_CODE _exchange_update_store_data_state(store_data_t *store_data, mcl_bool_t send_operation_successful);
143 
144 // This is for clearing the already sent data from the store :
146 
147 // This is used for getting the content info such as content id and types for meta and payload of the current store data :
148 static E_MCL_ERROR_CODE _exchange_store_data_get_content_info(store_data_t *store_data, string_t **meta_content_type, string_t **meta_content_id,
149  string_t **payload_content_type);
150 
151 // This function performs the initial operations of an http_request object, like adding the common headers :
152 static E_MCL_ERROR_CODE _exchange_initialize_http_request_headers(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication);
153 
154 // This function performs the final operations of an http_reqeust object, like adding the jwt header and closing the boundaries:
155 static E_MCL_ERROR_CODE _exchange_finalize_http_request(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication);
156 
157 // generates the jwt authentication header and adds to the request if with_authentication is MCL_TRUE. Else, does nothing.
158 static E_MCL_ERROR_CODE _add_authentication_header_to_request(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication);
159 
160 // This is the callback function given as an argument to http_request_add_tuple function to get the payload from buffer.
161 // Returns the number of actual written count. user_context is not currently used.
162 static mcl_size_t _get_payload_from_buffer(void *destination, void *source, mcl_size_t size, void *user_context);
163 
164 // This is the callback function given as an argument to http_request_add_tuple function to get the payload from file.
165 // Returns the number of actual written count. user_context is not currently used.
166 static mcl_size_t _get_payload_from_file(void *destination, void *file_descriptor, mcl_size_t size, void *user_context);
167 
168 #if MCL_STREAM_ENABLED
169 // This is the http client read callback for stream operation. This function fills the provided buffer with the http reqeust payload data generated from the store.
170 mcl_size_t _stream_callback(void *buffer, mcl_size_t size, mcl_size_t count, void *user_context);
171 #endif
172 
173 // Composes JSON string for onboarding with RSA security profile.
174 static E_MCL_ERROR_CODE _compose_rsa_onboarding_json(security_handler_t * security_handler, string_t **payload);
175 
176 // Composes JSON string for key rotation with RSA security profile.
177 static E_MCL_ERROR_CODE _compose_rsa_key_rotation_json(security_handler_t * security_handler, string_t **payload);
178 
179 // Adds key json object to keys json array.
180 static E_MCL_ERROR_CODE _add_key_to_keys_array(json_t *root, json_t **json_object);
181 
182 // Checks if the path provided is accessible.
183 static E_MCL_ERROR_CODE _check_file_path(const char *file_name);
184 
185 // Use custom function for loading register info.
189 
190 // Saves registration information.
192 
193 // Compose the payload for the request to be sent to /token endpoint.
195 
197 {
198  DEBUG_ENTRY("configuration_t *configuration = <%p>, http_processor_t **http_processor = <%p>", configuration, http_processor)
199 
200  // Return code for the functions to be called.
201  E_MCL_ERROR_CODE return_code;
202 
203  // initialize json module
205 
206  // initialize security module
208 
209  // Create http processor handle.
210  MCL_NEW(*http_processor);
211  ASSERT_CODE_MESSAGE(MCL_NULL != *http_processor, MCL_OUT_OF_MEMORY, "Memory can not be allocated for http processor.");
212 
213  // Make sure pointer members of http_processor which will be created inside this function are null initially.
214  // This is necessary for an unexpected call to http_processor_destroy() function.
215  (*http_processor)->http_client = MCL_NULL;
216  (*http_processor)->security_handler = MCL_NULL;
217 
218  // Set pointer to configuration parameters.
219  (*http_processor)->configuration = configuration;
220 
221  // Initialize http client.
222  return_code = http_client_initialize(configuration, &((*http_processor)->http_client));
223  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == return_code, http_processor_destroy(http_processor), return_code, "Http client initialization failed.");
224  MCL_DEBUG("Http client is successfully initialized.");
225 
226  // Initialize security handler.
227  return_code = security_handler_initialize(&((*http_processor)->security_handler));
228  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == return_code, http_processor_destroy(http_processor), return_code, "Security handler initialization failed.");
229  MCL_DEBUG("Security handler is successfully initialized.");
230 
231  // Load registration information via custom functions if both function pointers are not null
232  // or via file system if the path is specified.
233  if ((MCL_NULL != (*http_processor)->configuration->load_function.rsa && MCL_NULL != (*http_processor)->configuration->save_function.rsa) || MCL_NULL != (*http_processor)->configuration->store_path)
234  {
235  // Load registration information via custom functions if both function pointers are not null.
236  if(MCL_NULL != (*http_processor)->configuration->load_function.rsa && MCL_NULL != (*http_processor)->configuration->save_function.rsa)
237  {
238  return_code = _custom_load_register_info(*http_processor);
239  }
240  // Load registration information via file system if the path is specified.
241  else
242  {
243  if (MCL_OK == _check_file_path((*http_processor)->configuration->store_path->buffer))
244  {
245  if (MCL_SECURITY_SHARED_SECRET == (*http_processor)->configuration->security_profile)
246  {
247  return_code = storage_load_shared_secret_registration_information((*http_processor)->configuration->store_path, &((*http_processor)->security_handler->client_id), &((*http_processor)->security_handler->client_secret), &((*http_processor)->security_handler->registration_access_token), &((*http_processor)->security_handler->registration_client_uri));
248  }
249  else
250  {
251  return_code = storage_load_rsa_registration_information((*http_processor)->configuration->store_path, &((*http_processor)->security_handler->client_id), &((*http_processor)->security_handler->rsa.public_key), &((*http_processor)->security_handler->rsa.private_key), &((*http_processor)->security_handler->registration_access_token), &((*http_processor)->security_handler->registration_client_uri));
252  }
253  }
254  else
255  {
256  return_code = MCL_PATH_NOT_ACCESSIBLE;
257  }
258  }
259 
260  if (MCL_OK == return_code)
261  {
262  MCL_INFO("MCL is initialized with registration information provided in registration information file.");
263  }
264  else if (MCL_REGISTRATION_INFO_IS_NOT_LOADED == return_code)
265  {
266  if ((MCL_NULL == (*http_processor)->configuration->initial_access_token))
267  {
268  MCL_ERROR("No registration information is provided.");
269  return_code = MCL_NO_ACCESS_TOKEN_PROVIDED;
270  http_processor_destroy(http_processor);
271  }
272  else
273  {
274  // Generate RSA keys if RSA security profile is selected.
275  if (MCL_SECURITY_RSA_3072 == (*http_processor)->configuration->security_profile)
276  {
277  return_code = security_handler_generate_rsa_key((*http_processor)->security_handler);
278  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == return_code, http_processor_destroy(http_processor), return_code, "RSA keys can not be generated.");
279  MCL_DEBUG("RSA keys are generated.");
280  }
281  MCL_INFO("MCL is initialized to onboard with initial registration information.");
282  return_code = MCL_OK;
283  }
284  }
285  else
286  {
287  // MCL_PATH_NOT_ACCESSIBLE
288  http_processor_destroy(http_processor);
289  }
290  }
291  else
292  {
293  if ((MCL_NULL == (*http_processor)->configuration->initial_access_token))
294  {
295  MCL_ERROR("No registration information is provided.");
296  return_code = MCL_NO_ACCESS_TOKEN_PROVIDED;
297  http_processor_destroy(http_processor);
298  }
299  else
300  {
301  // Generate RSA keys if RSA security profile is selected.
302  if (MCL_SECURITY_RSA_3072 == (*http_processor)->configuration->security_profile)
303  {
304  return_code = security_handler_generate_rsa_key((*http_processor)->security_handler);
305  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == return_code, http_processor_destroy(http_processor), return_code, "RSA keys can not be generated.");
306  MCL_DEBUG("RSA keys are generated.");
307  }
308  MCL_INFO("MCL is initialized to onboard with initial registration information.");
309  return_code = MCL_OK;
310  }
311  }
312 
313  // TODO: Check whether or not below code should be inside communication_initialize
314  // Populate endpoints in configuration
315  (MCL_OK == return_code) && (return_code = _concatenate_host_and_endpoint((*http_processor)->configuration->mindsphere_hostname, &endpoint_uri[ENDPOINT_URI_REGISTER], &(*http_processor)->configuration->registration_endpoint));
316  (MCL_OK == return_code) && (return_code = _concatenate_host_and_endpoint((*http_processor)->configuration->mindsphere_hostname, &endpoint_uri[ENDPOINT_URI_EXCHANGE], &(*http_processor)->configuration->exchange_endpoint));
317  (MCL_OK == return_code) && (return_code = _concatenate_host_and_endpoint((*http_processor)->configuration->mindsphere_hostname, &endpoint_uri[ENDPOINT_URI_ACCESS_TOKEN], &(*http_processor)->configuration->access_token_endpoint));
318 
319  DEBUG_LEAVE("retVal = <%d>", return_code);
320  return return_code;
321 }
322 
324 {
325  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
326 
327  E_MCL_ERROR_CODE result = MCL_FAIL;
328 
329  http_request_t *http_request = MCL_NULL;
330  http_response_t *http_response = MCL_NULL;
331  string_t *access_token = MCL_NULL;
332  string_t *registration_uri = MCL_NULL;
333  string_t *payload = MCL_NULL;
334  string_t *correlation_id = MCL_NULL;
335  mcl_size_t header_size = 6;
336  E_MCL_HTTP_METHOD http_method;
337 
338  // Determine if onboarding or key rotation is requested.
339  if (MCL_NULL == http_processor->security_handler->registration_access_token)
340  {
341  // Compose payload of the request.
343  {
344  result = string_initialize_new("{}", 2, &payload);
345  }
346  else if (MCL_SECURITY_RSA_3072 == http_processor->configuration->security_profile)
347  {
348  result = _compose_rsa_onboarding_json(http_processor->security_handler, &payload);
349  }
350  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Payload of onboarding request can not be constructed.");
351 
352  http_method = MCL_HTTP_POST;
353  registration_uri = http_processor->configuration->registration_endpoint;
354 
355  // Add "Bearer" before initial access token.
356  result = string_initialize_new(MCL_NULL, 7 + http_processor->configuration->initial_access_token->length, &access_token);
357  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == result, string_destroy(&payload), result, "Memory can not be allocated for initial access token.");
358  result = string_util_snprintf(access_token->buffer, access_token->length + 1, "Bearer %s", http_processor->configuration->initial_access_token->buffer);
359  }
360  else
361  {
362  // Compose payload of the request.
364  {
365  // TODO: Compose payload as JSON string using JSON functions
366  if (MCL_OK == (result = string_initialize_new(MCL_NULL, 16 + http_processor->security_handler->client_id->length, &payload)))
367  {
368  result = string_util_snprintf(payload->buffer, payload->length + 1, "{\"client_id\":\"%s\"}", http_processor->security_handler->client_id->buffer);
369  }
370  }
371  else if (MCL_SECURITY_RSA_3072 == http_processor->configuration->security_profile)
372  {
373  result = _compose_rsa_key_rotation_json(http_processor->security_handler, &payload);
374  }
375  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == result, string_destroy(&payload), result, "Payload of key rotation request can not be constructed.");
376 
377  http_method = MCL_HTTP_PUT;
378  registration_uri = http_processor->security_handler->registration_client_uri;
379 
380  // Add "Bearer" before registration access token.
381  result = string_initialize_new(MCL_NULL, 7 + http_processor->security_handler->registration_access_token->length, &access_token);
382  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == result, string_destroy(&payload), result, "Memory can not be allocated for registration access token.");
383  result = string_util_snprintf(access_token->buffer, access_token->length + 1, "Bearer %s",
385  }
386 
387  (MCL_OK == result) && (result = http_request_initialize(http_method, registration_uri, header_size, payload->length, HTTP_REQUEST_RESIZE_ENABLED, http_processor->configuration->user_agent,
388  http_processor->configuration->max_http_payload_size, &http_request));
389 
390  if (MCL_OK != result)
391  {
392  string_destroy(&payload);
393  string_destroy(&access_token);
394  http_request_destroy(&http_request);
395  MCL_ERROR_RETURN(result, "HTTP request can not be initialized.");
396  }
397 
398  // Compose header and payload fields of HTTP request.
399  string_util_memcpy(http_request->payload, payload->buffer, payload->length);
401  (MCL_OK == result) && (result = http_request_add_header(http_request, &http_header_names[HTTP_HEADER_ACCEPT], &content_type_values[CONTENT_TYPE_APPLICATION_JSON]));
402  (MCL_OK == result) && (result = http_request_add_header(http_request, &http_header_names[HTTP_HEADER_AUTHORIZATION], access_token));
403 
404  (MCL_OK == result) && (result = _generate_correlation_id_string(&correlation_id));
405  (MCL_OK == result) && (result = http_request_add_header(http_request, &http_header_names[HTTP_HEADER_CORRELATION_ID], correlation_id));
406 
407  // Send the request and get the response.
408  if (MCL_OK == result)
409  {
410  // Send the onboarding request and retrieve the response.
411  if (MCL_OK != (result = http_client_send(http_processor->http_client, http_request, MCL_NULL, &http_response)))
412  {
413  MCL_ERROR("HTTP request can not be sent to the server.");
414  }
415  else
416  {
417  E_MCL_ERROR_CODE server_response = _evaluate_response_codes(http_response);
418  if ((MCL_NULL == http_processor->security_handler->registration_access_token)
419  && (MCL_OK != (result = (MCL_CREATED == server_response ? MCL_OK : (MCL_OK == server_response ? MCL_UNEXPECTED_RESULT_CODE : server_response)))))
420  {
421  MCL_ERROR("Onboarding failed: Correlation-ID = \"%s\"", correlation_id->buffer);
422  }
423  else if ((MCL_NULL != http_processor->security_handler->registration_access_token)
424  && (MCL_OK != (result = server_response)))
425  {
426  MCL_ERROR("Key rotation failed: Correlation-ID = \"%s\"", correlation_id->buffer);
427  }
428  else
429  {
430  MCL_INFO("Correlation-ID = \"%s\"", correlation_id->buffer);
432  {
433  result = _process_registration_response_shared_secret(http_processor, http_response);
434  }
435  else
436  {
437  result = _process_registration_response_rsa_3072(http_processor, http_response);
438  }
439 
440  if (MCL_OK == result)
441  {
442  result = _save_registration_information(http_processor);
443  }
444  }
445  }
446  }
447 
448  // Clean up.
449  string_destroy(&correlation_id);
450  string_destroy(&payload);
451  string_destroy(&access_token);
452  http_request_destroy(&http_request);
453  http_response_destroy(&http_response);
454 
455  DEBUG_LEAVE("retVal = <%d>", result);
456  return result;
457 }
458 
460 {
461  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
462 
463  E_MCL_ERROR_CODE code;
464 
465  // These will be used in any security profile.
466  char *client_id = MCL_NULL;
467  char *registration_access_token = MCL_NULL;
468  char *registration_uri = MCL_NULL;
469 
470  string_t *client_id_string = MCL_NULL;
471  string_t *registration_access_token_string = MCL_NULL;
472  string_t *registration_uri_string = MCL_NULL;
473 
474  // For shared secret.
475  char *client_secret = MCL_NULL;
476  string_t *client_secret_string = MCL_NULL;
477 
478  // For RSA 3072.
479  char *public_key = MCL_NULL;
480  char *private_key = MCL_NULL;
481 
482  mcl_bool_t callbacks_are_used = (MCL_NULL != http_processor->configuration->load_function.shared_secret && MCL_NULL != http_processor->configuration->save_function.shared_secret);
483  ASSERT_CODE_MESSAGE(MCL_TRUE == (callbacks_are_used || MCL_NULL != http_processor->configuration->store_path), MCL_FAIL, "There is no way to update security information.");
484 
485  if(callbacks_are_used)
486  {
488  {
489  code = http_processor->configuration->load_function.shared_secret(&client_id, &client_secret, &registration_access_token, &registration_uri);
490  }
491  else
492  {
493  code = http_processor->configuration->load_function.rsa(&client_id, &public_key, &private_key, &registration_access_token, &registration_uri);
494  }
495  }
496  else
497  {
499  {
500  code = storage_load_shared_secret_registration_information(http_processor->configuration->store_path, &client_id_string, &client_secret_string, &registration_access_token_string, &registration_uri_string);
501  client_secret = client_secret_string->buffer;
502  }
503  else
504  {
505  code = storage_load_rsa_registration_information(http_processor->configuration->store_path, &client_id_string, &public_key, &private_key, &registration_access_token_string, &registration_uri_string);
506  }
507  client_id = client_id_string->buffer;
508  registration_access_token = registration_access_token_string->buffer;
509  }
510 
511  // If loading security information is failed, user must have set all parameters to NULL. No need to clean up.
512  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "Security information cannot be loaded.");
513 
514  // Registration URI will not be used.
515  MCL_NULL == registration_uri_string ? MCL_FREE(registration_uri) : string_destroy(&registration_uri_string);
516 
517  // Check whether client id is correct.
518  code = string_compare_with_cstr(http_processor->security_handler->client_id, client_id);
519 
520  MCL_NULL == client_id_string ? MCL_FREE(client_id) : string_destroy(&client_id_string);
521 
522  if(MCL_OK == code)
523  {
525  {
526  code = string_compare_with_cstr(http_processor->security_handler->client_secret, client_secret);
527  (MCL_OK == code) && (code = string_compare_with_cstr(http_processor->security_handler->registration_access_token, registration_access_token));
528  }
529  else
530  {
531  mcl_size_t length = string_util_strlen(http_processor->security_handler->rsa.private_key);
532  code = MCL_FAIL;
533 
534  if(length == string_util_strlen(private_key))
535  {
536  code = string_util_strncmp(private_key, http_processor->security_handler->rsa.private_key, length);
537  }
538  }
539 
540  // If code == MCL_OK, client secret is not different from what we have.
541  code = (MCL_OK == code) ? MCL_SECURITY_UP_TO_DATE : MCL_OK;
542  }
543 
544  if(MCL_OK == code && callbacks_are_used)
545  {
546  code = string_initialize_dynamic(registration_access_token, 0, &registration_access_token_string);
547 
548  if(MCL_OK == code && MCL_SECURITY_SHARED_SECRET == http_processor->configuration->security_profile)
549  {
550  code = string_initialize_dynamic(client_secret, 0, &client_secret_string);
551  }
552  }
553 
554  if(MCL_OK == code)
555  {
556  // Everything is fine, now we can replace old information.
557  // There is no need to check security profile, unrelated parameters will be just reassigned to NULL.
559  string_destroy(&(http_processor->security_handler->client_secret));
560  MCL_FREE(http_processor->security_handler->rsa.public_key);
561  MCL_FREE(http_processor->security_handler->rsa.private_key);
562 
563  http_processor->security_handler->registration_access_token = registration_access_token_string;
564  http_processor->security_handler->client_secret = client_secret_string;
565  http_processor->security_handler->rsa.public_key = public_key;
566  http_processor->security_handler->rsa.private_key = private_key;
567  }
568  else
569  {
570  MCL_NULL == registration_access_token_string ? MCL_FREE(registration_access_token) : string_destroy(&registration_access_token_string);
571  MCL_NULL == client_secret_string ? MCL_FREE(client_secret) : string_destroy(&client_secret_string);
572  MCL_FREE(public_key);
573  MCL_FREE(private_key);
574  }
575 
576  DEBUG_LEAVE("retVal = <%d>", code);
577  return code;
578 }
579 
581 {
582  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
583 
584  E_MCL_ERROR_CODE code;
585  string_t *request_payload = MCL_NULL;
586  string_t *correlation_id = MCL_NULL;
587  http_request_t *request = MCL_NULL;
588  http_response_t *response = MCL_NULL;
589  E_MCL_ERROR_CODE optional_field_code = MCL_FAIL;
590  string_t *server_time_header = MCL_NULL;
591  json_t *response_payload = MCL_NULL;
592  json_t *access_token = MCL_NULL;
593 
594  // Create access token request payload.
595  code = _compose_access_token_request_payload(http_processor, &request_payload);
596 
597  // Initialize HTTP request.
598  (MCL_OK == code) && (code = http_request_initialize(MCL_HTTP_POST, http_processor->configuration->access_token_endpoint, 2, request_payload->length, HTTP_REQUEST_RESIZE_ENABLED, http_processor->configuration->user_agent,
599  http_processor->configuration->max_http_payload_size, &request));
600 
601  // Add headers to the request.
603  (MCL_OK == code) && (code = _generate_correlation_id_string(&correlation_id));
604  (MCL_OK == code) && (code = http_request_add_header(request, &http_header_names[HTTP_HEADER_CORRELATION_ID], correlation_id));
605 
606  // Add payload to the request.
607  if (MCL_OK == code)
608  {
609  string_util_memcpy(request->payload, request_payload->buffer, request_payload->length);
610  }
611  string_destroy(&request_payload);
612 
613  // Send the request.
614  (MCL_OK == code) && (code = http_client_send(http_processor->http_client, request, MCL_NULL, &response));
615  http_request_destroy(&request);
616 
617  // Get server time which is an optional header in the response.
618  (MCL_OK == code) && (optional_field_code = http_response_get_header(response, http_header_names[HTTP_HEADER_SERVER_TIME].buffer, &server_time_header));
619 
620  if(MCL_OK == code)
621  {
622  if (MCL_OK == optional_field_code)
623  {
625  http_processor->security_handler->last_token_time = server_time_header;
626  }
627 
628  code = _evaluate_response_codes(response);
629  if(MCL_OK == code)
630  {
631  MCL_INFO("Correlation-ID = \"%s\"", correlation_id->buffer);
632  }
633  else
634  {
635  MCL_ERROR("Getting access token failed. Correlation-ID = \"%s\"", correlation_id->buffer);
636  }
637  }
638  string_destroy(&correlation_id);
639 
640  // Parse the response to get access token.
641  (MCL_OK == code) && (code = json_util_parse_with_size((const char*)http_response_get_payload(response), response->payload_size, &response_payload));
642  http_response_destroy(&response);
643 
644  (MCL_OK == code) && (code = json_util_get_object_item(response_payload, JSON_NAME_ACCESS_TOKEN, &access_token));
645 
646  string_destroy(&http_processor->security_handler->access_token);
647  (MCL_OK == code) && (code = json_util_get_string(access_token, &http_processor->security_handler->access_token));
648 
649  MCL_FREE(access_token);
650  json_util_destroy(&response_payload);
651 
652  DEBUG_LEAVE("retVal = <%d>", code);
653  return code;
654 }
655 
656 #if MCL_FILE_DOWNLOAD_ENABLED
657 E_MCL_ERROR_CODE http_processor_download(http_processor_t *http_processor, mcl_uint8_t * buffer, mcl_size_t buffer_size, mcl_size_t start_byte, mcl_size_t end_byte, string_t *file_id, mcl_bool_t with_range, file_t **file)
658 {
659  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, mcl_uint8_t *buffer = <%p>, mcl_size_t start_byte = <%u>, mcl_size_t end_byte <%u>, string_t *file_id = <%p>, mcl_bool_t with_range = <%d>, file_t **file = <%p>",
660  http_processor, buffer, start_byte, end_byte, file_id, with_range, file)
661 
662  // Prepare local vars
663  http_request_t *request = MCL_NULL;
664  mcl_size_t header_size = 3;
665  string_t *uri = MCL_NULL;
666  string_t *uri_temp = MCL_NULL;
667 
668  E_MCL_ERROR_CODE result = _concatenate_host_and_endpoint(http_processor->configuration->mindsphere_hostname, &endpoint_uri[ENDPOINT_URI_DOWNLOAD], &uri_temp);
669  (MCL_OK == result) && (result = _concatenate_host_and_endpoint(uri_temp, file_id, &uri));
670  string_destroy(&uri_temp);
671 
672  (MCL_OK == result) && (result = http_request_initialize(MCL_HTTP_GET, uri, header_size, 0, HTTP_REQUEST_RESIZE_ENABLED, http_processor->configuration->user_agent,
673  http_processor->configuration->max_http_payload_size, &request));
674  string_destroy(&uri);
675 
676  // Add authentication header
677  (MCL_OK == result) && (result = _add_authentication_header_to_request(http_processor, request, MCL_TRUE));
678 
679  string_t *accept_header = MCL_NULL;
680  (MCL_OK == result) && (result = string_initialize_static("application/octet-stream", 0, &accept_header));
681  (MCL_OK == result) && (result = http_request_add_header(request, &http_header_names[HTTP_HEADER_ACCEPT], accept_header));
682  string_destroy(&accept_header);
683 
684  // If download requested for range then add Range header
685  (MCL_OK == result) && (MCL_TRUE == with_range) && (result = _add_range_header(request, start_byte, end_byte));
686 
687  string_t *correlation_id = MCL_NULL;
688  (MCL_OK == result) && (result = _generate_correlation_id_string(&correlation_id));
689  (MCL_OK == result) && (result = http_request_add_header(request, &http_header_names[HTTP_HEADER_CORRELATION_ID], correlation_id));
690 
691  // Send request
692  http_response_t *response = MCL_NULL;
693  (MCL_OK == result) && (result = http_client_send(http_processor->http_client, request, MCL_NULL, &response));
694  http_request_destroy(&request);
695 
696  if(MCL_OK == result)
697  {
698  E_MCL_ERROR_CODE server_response = _evaluate_response_codes(response);
699  result = (MCL_PARTIAL_CONTENT == server_response ? MCL_OK : server_response);
700 
701  if(MCL_OK == result)
702  {
703  MCL_INFO("Correlation-ID = \"%s\"", correlation_id->buffer);
704  }
705  else
706  {
707  MCL_ERROR("Acknowledge events failed. Correlation-ID = \"%s\"", correlation_id->buffer);
708  }
709  }
710 
711  string_destroy(&correlation_id);
712 
713  // Get file name.
714  string_t *content_disposition_header = MCL_NULL;
715  (MCL_OK == result) && (result = http_response_get_header(response, http_header_names[HTTP_HEADER_CONTENT_DISPOSITION].buffer, &content_disposition_header));
716  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == result, http_response_destroy(&response), result, "Could not get header.");
717 
718  result = file_initialize("", MCL_NULL, "", "", MCL_NULL, file);
719 
720  if(MCL_NULL == *file)
721  {
722  http_response_destroy(&response);
723  string_destroy(&content_disposition_header);
724  MCL_ERROR_RETURN(result, "File initialization failed.");
725  }
726 
727  if (MCL_NULL != content_disposition_header)
728  {
729  result = _get_file_name(content_disposition_header->buffer, &(*file)->meta.payload.details.file_details.file_name);
730  string_destroy(&content_disposition_header);
731 
732  if(MCL_OK != result)
733  {
734  file_destroy(file);
735  http_response_destroy(&response);
736  MCL_ERROR_RETURN(result, "Getting file name failed.")
737  }
738  }
739 
740  // Copy response payload to given buffer.
741  (*file)->payload.size = response->payload_size;
742 
743  if (buffer_size >= response->payload_size)
744  {
745  string_util_memcpy(buffer, response->payload, response->payload_size);
746  (*file)->payload.buffer = buffer;
747  }
748  else
749  {
750  result = MCL_BUFFER_OVERFLOW_ERROR;
751  }
752 
753  if (MCL_TRUE == with_range)
754  {
755  // Add range values do file
756  ASSERT_CODE_MESSAGE(MCL_OK == _add_actual_range_to_file(response, *file), MCL_FAIL, "Could not obtain range values from Content-Range header");
757  }
758 
759  http_response_destroy(&response);
760 
761  DEBUG_LEAVE("retVal = <%d>", result);
762  return result;
763 }
764 #endif
765 
767 {
768  DEBUG_ENTRY("string_t *host = <%p>, string_t *endpoint = <%p>, string_t **uri = <%p>", host, endpoint, uri)
769 
770  E_MCL_ERROR_CODE return_code = MCL_FAIL;
771 
772  // Size of the URI string (host and endpoint with '/' in between).
773  mcl_size_t uri_length = host->length + endpoint->length + 1;
774 
775  // Allocate memory for the request URI.
776  if (MCL_OK == (return_code = string_initialize_new(MCL_NULL, uri_length, uri)))
777  {
778  return_code = string_util_snprintf((*uri)->buffer, uri_length + 1, "%s/%s", host->buffer, endpoint->buffer);
779  ASSERT_STATEMENT_CODE_MESSAGE(MCL_OK == return_code, string_destroy(uri), return_code, "Host and endpoint can not be concatenated.");
780  }
781 
782  DEBUG_LEAVE("retVal = <%d>", return_code);
783  return return_code;
784 }
785 
786 E_MCL_ERROR_CODE http_processor_exchange(http_processor_t *http_processor, store_t *store, void **reserved)
787 {
788  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, store_t *store = <%p>, void **reserved = <%p>", http_processor, store, reserved)
789 
790  E_MCL_ERROR_CODE result;
791 
792  // TODO : Below var values needs to be optimized :
793  mcl_size_t header_size = 3;
794  mcl_size_t payload_size = 200;
795 
796  // Unused parameter.
797  (void)reserved;
798 
799  ASSERT_CODE_MESSAGE(0 < store->high_priority_list->count + store->low_priority_list->count, MCL_STORE_IS_EMPTY, "Received store doesn't have any data inside!");
800 
801  // Continue generating an http request and send, until no data left in the store OR an error received:
802  do
803  {
804  // Prepare local vars
805  http_request_t *request = MCL_NULL;
806  string_t *correlation_id = MCL_NULL;
807 
808  MCL_DEBUG("Start of a fill and send iteration");
809 
810  result = http_request_initialize(MCL_HTTP_POST, http_processor->configuration->exchange_endpoint, header_size, payload_size, HTTP_REQUEST_RESIZE_ENABLED, http_processor->configuration->user_agent,
811  http_processor->configuration->max_http_payload_size, &request);
812 
813  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Initializing HTTP Request has failed!");
814 
815  result = _exchange_initialize_http_request_headers(http_processor, request, MCL_TRUE);
816 
817  if (MCL_OK != result)
818  {
819  http_request_destroy(&request);
820  MCL_ERROR_RETURN(result, "Initializing HTTP Request headers failed!");
821  }
822 
823  MCL_DEBUG("A new http_request has been initialized");
824 
825  result = _exchange_fill_http_request(http_processor, store, request);
826 
827  (MCL_OK == result) && (result = _generate_correlation_id_string(&correlation_id));
828  (MCL_OK == result) && (result = http_request_add_header(request, &http_header_names[HTTP_HEADER_CORRELATION_ID], correlation_id));
829 
830  if (MCL_OK == result)
831  {
832  // Check if http_request is ready to be sent.
833  // Send it if it is ready
834  // request ready to be sent :
835  http_response_t *response = MCL_NULL;
836 
837  // Not checking the result of send operation. Result will be evaluated based on the response.
838  result = http_client_send(http_processor->http_client, request, MCL_NULL, &response);
839 
840  // request can be destroyed now ;
841  http_request_destroy(&request);
842 
843  // then evaluate the response :
844  result = _exchange_evaluate_response(store, result, response, NULL, correlation_id);
845 
846  if (MCL_OK != result)
847  {
848  string_destroy(&correlation_id);
849  MCL_DEBUG("Evaluating the result returned as failed. Terminating the exchange operation.");
850  break;
851  }
852  }
853  else
854  {
855  // error case. Return the error.
856  string_destroy(&correlation_id);
857  MCL_DEBUG("An error has been occured during http request preparation = <%d>. Terminating the exchange operation.", result);
858  http_request_destroy(&request);
859  break;
860  }
861 
862  string_destroy(&correlation_id);
863  }
864  while (0 < store_get_data_count(store));
865 
866  DEBUG_LEAVE("retVal = <%d>", result);
867  return result;
868 }
869 
870 E_MCL_ERROR_CODE http_processor_stream(http_processor_t *http_processor, store_t *store, void **reserved)
871 {
872 #if MCL_STREAM_ENABLED
873  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, store_t *store = <%p>, void **reserved = <%p>", http_processor, store, reserved)
874 
875  ASSERT_CODE_MESSAGE(0 < store->high_priority_list->count + store->low_priority_list->count, MCL_STORE_IS_EMPTY, "Received store doesn't have any data inside!");
876 
877  // 0- Prepare local vars
878  http_request_t *request = MCL_NULL;
879  http_response_t *response = MCL_NULL;
880 
881  // TODO : Below var values needs to be corrected :
882  mcl_size_t header_size = 2;
883  mcl_size_t payload_size = 0;
884 
885  // adjust callback function and data :
886  http_processor_stream_callback_context_t http_processor_callback_context =
887  {
888  http_processor, store, MCL_NULL, 0, MCL_OK
889  };
890  http_client_send_callback_info_t send_callback_info;
891  send_callback_info.read_callback = _stream_callback;
892  send_callback_info.user_context = &http_processor_callback_context;
893 
894  E_MCL_ERROR_CODE result = MCL_FAIL;
895 
896  while (0 < store_get_data_count(store))
897  {
898  // Initialize a new http_request:
899  result = http_request_initialize(MCL_HTTP_POST, http_processor->configuration->exchange_endpoint, header_size, payload_size, HTTP_REQUEST_RESIZE_DISABLED, http_processor->configuration->user_agent,
900  http_processor->configuration->max_http_payload_size, &request);
901 
902  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Initializing HTTP Request is failed!");
903 
904  // update the request info in callback info :
905  http_processor_callback_context.request = request;
906 
907  result = _exchange_initialize_http_request_headers(http_processor, request, MCL_TRUE);
908 
909  if (MCL_OK != result)
910  {
911  http_request_destroy(&request);
912  MCL_ERROR_RETURN(result, "Initializing HTTP Request headers failed!");
913  }
914 
915  string_t *correlation_id = MCL_NULL;
916  (MCL_OK == result) && (result = _generate_correlation_id_string(&correlation_id));
917  (MCL_OK == result) && (result = http_request_add_header(request, &http_header_names[HTTP_HEADER_CORRELATION_ID], correlation_id));
918  (MCL_OK == result) && (result = http_client_send(http_processor->http_client, request, &send_callback_info, &response));
919 
920  // clean up request :
921  http_request_destroy(&request);
922 
923  // then evaluate the response :
924  result = _exchange_evaluate_response(store, result, response, NULL, correlation_id);
925  string_destroy(&correlation_id);
926 
927  if (MCL_OK != result)
928  {
929  MCL_DEBUG("Evaluating the result returned as failed. Terminating the exchange operation.");
930  break;
931  }
932  }
933 
934  DEBUG_LEAVE("retVal = <%d>", result);
935  return result;
936 #else
937  // Unused parameters.
938  (void)http_processor;
939  (void)store;
940  (void)reserved;
941 
943 #endif // MCL_STREAM_ENABLED
944 }
945 
947 {
948  DEBUG_ENTRY("http_processor_t **http_processor = <%p>", http_processor)
949 
950  if (MCL_NULL != *http_processor)
951  {
952  // Destroy http client handler.
953  http_client_destroy(&((*http_processor)->http_client));
954 
955  // Destroy security handler.
956  security_handler_destroy(&((*http_processor)->security_handler));
957 
958  // TODO: Check whether or not below code should be in communication_destroy.
959  string_destroy(&((*http_processor)->configuration->access_token_endpoint));
960  string_destroy(&((*http_processor)->configuration->exchange_endpoint));
961  string_destroy(&((*http_processor)->configuration->registration_endpoint));
962 
963  // Free http_processor handle.
964  MCL_FREE(*http_processor);
965 
966  MCL_DEBUG("Http processor handle is destroyed.");
967  }
968  else
969  {
970  MCL_DEBUG("Http processor handle is already NULL.");
971  }
972 
973  DEBUG_LEAVE("retVal = void");
974 }
975 
977 {
978  DEBUG_ENTRY("store_data_t *current_store_data = <%p>, http_request_t *request = <%p>", current_store_data, request)
979 
980  E_MCL_ERROR_CODE result = MCL_OK;
981 
982  mcl_size_t available_size_in_request;
983 
984  // get content type and id to use when calling add_tuple/single :
985  string_t *meta_content_type = MCL_NULL;
986  string_t *payload_content_type = MCL_NULL;
987  string_t *meta_content_id = MCL_NULL;
988 
989  mcl_size_t left_meta_size;
990  mcl_size_t left_payload_size;
991 
992  // If stream_info is NULL, initialize it :
993  if (MCL_NULL == current_store_data->stream_info)
994  {
995  MCL_NEW(current_store_data->stream_info);
996  ASSERT_CODE_MESSAGE(MCL_NULL != current_store_data->stream_info, MCL_OUT_OF_MEMORY, "Memory can not be allocated for stream_info.");
997 
998  // Initialize stream information.
999  current_store_data->stream_info->meta_stream_index = 0;
1000  current_store_data->stream_info->payload_stream_index = 0;
1001  current_store_data->stream_info->tuple_subboundary = MCL_NULL;
1002 
1003  // For explanation of -2 please check below usage :
1004  current_store_data->stream_info->meta_state = -2;
1005 
1006  // For explanation of -1 please check below usage :
1007  current_store_data->stream_info->payload_state = -1;
1008  }
1009 
1010  ASSERT_CODE_MESSAGE(MCL_OK == _exchange_store_data_get_content_info(current_store_data, &meta_content_type, &meta_content_id, &payload_content_type), MCL_FAIL,
1011  "Get content type and id info failed!");
1012 
1013  // tuple
1014  MCL_DEBUG("Data is tuple.");
1015 
1016  // start tuple if not started before :
1017  if (-2 == current_store_data->stream_info->meta_state)
1018  {
1019  result = http_request_start_tuple(request);
1020  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Starting tuple is failed!");
1021 
1022  // increasing meta state to -1 to indicate that a tuple is opened for this:
1023  current_store_data->stream_info->meta_state++;
1024  }
1025 
1026  // start tuple sub section for meta if not started before
1027  if (-1 == current_store_data->stream_info->meta_state)
1028  {
1029  result = http_request_start_tuple_sub_section(request, meta_content_type, meta_content_id, &(current_store_data->stream_info->tuple_subboundary));
1030  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Starting tuple section for meta is failed!");
1031 
1032  // increasing meta state to 0 to indicate that a subsection is opened for this:
1033  current_store_data->stream_info->meta_state++;
1034  }
1035 
1036  // calculate meta left size :
1037  left_meta_size = current_store_data->meta->length - current_store_data->stream_info->meta_stream_index;
1038  if (0 < left_meta_size)
1039  {
1040  // get available space :
1041  available_size_in_request = http_request_get_available_space_for_raw_data(request);
1042 
1043  if (0 < available_size_in_request)
1044  {
1045  // compare with left meta size and calculate how much meta can be written ( use left_meta_size to hold that) :
1046  if (left_meta_size > available_size_in_request)
1047  {
1048  MCL_DEBUG("Left meta size has been reduced to available size in request = <%u>", available_size_in_request);
1049  left_meta_size = available_size_in_request;
1050  }
1051 
1052  // write left meta :
1054  (void *)(current_store_data->meta->buffer + current_store_data->stream_info->meta_stream_index), left_meta_size, MCL_NULL);
1055  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Add raw data has been failed for meta!");
1056 
1057  // left meta has been written. mark the position:
1058  current_store_data->stream_info->meta_stream_index += left_meta_size;
1059  }
1060  else
1061  {
1062  MCL_DEBUG("Available space in request is 0.");
1064  }
1065  }
1066 
1067  // check if meta write completed :
1068  left_meta_size = current_store_data->meta->length - current_store_data->stream_info->meta_stream_index;
1069  if (0 == left_meta_size)
1070  {
1071  // start a sub section for payload if it is not started before :
1072  if (-1 == current_store_data->stream_info->payload_state)
1073  {
1074  result = http_request_start_tuple_sub_section(request, payload_content_type, MCL_NULL, &(current_store_data->stream_info->tuple_subboundary));
1075  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Starting tuple section for payload is failed!");
1076 
1077  // increasing payload state to 0 to indicate that a subsection is opened for this:
1078  current_store_data->stream_info->payload_state++;
1079  }
1080 
1081  left_payload_size = current_store_data->payload_size - current_store_data->stream_info->payload_stream_index;
1082  if ((0 < left_payload_size) || (STORE_DATA_STREAM == current_store_data->type))
1083  {
1084  available_size_in_request = http_request_get_available_space_for_raw_data(request);
1085 
1086  if (0 < available_size_in_request)
1087  {
1088  // compare with left meta size and calculate how much meta can be written ( use left_meta_size to hold that) :
1089  if (left_payload_size > available_size_in_request)
1090  {
1091  MCL_DEBUG("Left payload size has been equalized to available size in request = <%u>", available_size_in_request);
1092  left_payload_size = available_size_in_request;
1093  }
1094 
1095  // write left meta :
1096  if (STORE_DATA_FILE == current_store_data->type)
1097  {
1098  file_t *file;
1099 
1100  MCL_DEBUG("Type is STORE_DATA_FILE. Calling file read callback function.");
1101 
1102  file = (file_t *)current_store_data->data;
1103  result = http_request_add_raw_data(request, _get_payload_from_file, MCL_NULL, (void *)(file->descriptor), left_payload_size, MCL_NULL);
1104  }
1105  else if (STORE_DATA_STREAM == current_store_data->type)
1106  {
1107  mcl_size_t actual_written = 0;
1108  stream_data_t *stream_data = (stream_data_t *)current_store_data->data;
1109  MCL_DEBUG("Type is STORE_DATA_STREAM. Calling user provided read callback function = <%p>, with user_context = <%p>", stream_data->read_callback,
1110  stream_data->user_context);
1111 
1112  // Using the available size since this is a stream data :
1113  result = http_request_add_raw_data(request, (payload_copy_callback_t)stream_data->read_callback, stream_data->user_context, MCL_NULL,
1114  available_size_in_request, &actual_written);
1115 
1116  if ((MCL_OK == result) && (0 == actual_written))
1117  {
1118  MCL_DEBUG("User callback completed writing data.");
1119 
1120  // set payload_size and payload_stream_index to 0 to mark it WRITTEN below :
1121  current_store_data->payload_size = 0;
1122  current_store_data->stream_info->payload_stream_index = 0;
1123  }
1124  }
1125  else
1126  {
1127  MCL_DEBUG("Type is <standard types>. Calling memory read callback function.");
1129  (void *)(current_store_data->payload_buffer + current_store_data->stream_info->payload_stream_index),
1130  left_payload_size, MCL_NULL);
1131  }
1132 
1133  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Add raw data has been failed for payload!");
1134 
1135  // left meta has been written. mark the position:
1136  current_store_data->stream_info->payload_stream_index += left_payload_size;
1137  }
1138  else
1139  {
1140  MCL_DEBUG("Available space in request is 0.");
1142  }
1143  }
1144  }
1145 
1146  // if meta and payload written is completed end tuple :
1147  left_payload_size = current_store_data->payload_size - current_store_data->stream_info->payload_stream_index;
1148  if ((0 == left_meta_size) && (0 == left_payload_size))
1149  {
1150  result = http_request_end_tuple_sub_section(request, current_store_data->stream_info->tuple_subboundary);
1151  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "End tuple section has been failed!");
1152 
1153  MCL_DEBUG("Meta and payload have been written completely. Updating its state to WRITTEN.");
1154  store_data_set_state(current_store_data, DATA_STATE_WRITTEN);
1155  }
1156 
1157  DEBUG_LEAVE("retVal = <%d>", result);
1158  return result;
1159 }
1160 
1162 {
1163  DEBUG_ENTRY("store_data_t *current_store_data = <%p>, http_request_t *request = <%p>", current_store_data, request)
1164 
1165  // Decide whether to add a single or tuple :
1166  // if current item has both a meta and a payload, it requires a tuple to be sent
1167 
1168  E_MCL_ERROR_CODE result;
1169 
1170  // if this is a stream_data, we couldn't know its size. Safe action to do so is to return MCL_HTTP_REQUEST_NO_MORE_SPACE.
1171  // This way it will redirected to _exchange_add_current_data_to_request_by_streaming() function :
1172  if (STORE_DATA_STREAM == current_store_data->type)
1173  {
1174  MCL_DEBUG("This is a streaming data. We don't know the size. Returning MCL_HTTP_REQUEST_NO_MORE_SPACE to make it be written with stream method.");
1176  }
1177  else
1178  {
1179  // get content type and id to use when calling add_tuple/single :
1180  string_t *meta_content_type = MCL_NULL;
1181  string_t *payload_content_type = MCL_NULL;
1182  string_t *meta_content_id = MCL_NULL;
1183  ASSERT_CODE_MESSAGE(MCL_OK == _exchange_store_data_get_content_info(current_store_data, &meta_content_type, &meta_content_id, &payload_content_type), MCL_FAIL,
1184  "Get content type and id info failed!");
1185 
1186  // Check if the store item is file or not.
1187  if (STORE_DATA_FILE == current_store_data->type)
1188  {
1189  file_t *file = (file_t *)current_store_data->data;
1190  result = http_request_add_tuple(request, current_store_data->meta, meta_content_type, _get_payload_from_file, MCL_NULL, file->descriptor,
1191  current_store_data->payload_size, payload_content_type);
1192  }
1193  else
1194  {
1195  result = http_request_add_tuple(request, current_store_data->meta, meta_content_type, _get_payload_from_buffer, MCL_NULL, current_store_data->payload_buffer,
1196  current_store_data->payload_size, payload_content_type);
1197  }
1198 
1199  // check the result and adjust written info of the data ::
1200  if (MCL_OK == result)
1201  {
1202  // successfully written. Update its state to written:
1203  store_data_set_state(current_store_data, DATA_STATE_WRITTEN);
1204  }
1205  else if (MCL_HTTP_REQUEST_NO_MORE_SPACE == result)
1206  {
1207  // meta and payload data couldn't be written to http_request. here we are not increasing write offset.
1208  MCL_DEBUG("No more space left in the request for normal writing the data.");
1209  }
1210  else
1211  {
1212  // error returned. not increasing write offset.
1213  // error will be directly returned.
1214  MCL_DEBUG("Error response received from http_request_add_tuple");
1215  }
1216  }
1217 
1218  DEBUG_LEAVE("retVal = <%d>", result);
1219  return result;
1220 }
1221 
1223 {
1224  DEBUG_ENTRY("store_data_t *store_data = <%p>", store_data)
1225 
1226  // Generate the meta/payload string based on the type:
1227  if (STORE_DATA_TIME_SERIES == store_data->type)
1228  {
1229  time_series_t *time_series;
1230  string_t *payload_string = MCL_NULL;
1231 
1232  MCL_DEBUG("Item type = <time_series>");
1233 
1234  time_series = (time_series_t *)store_data->data;
1235 
1236  // Generate the meta string :
1237  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(&time_series->meta, &store_data->meta), MCL_FAIL, "Get meta string from item meta for time_series has been failed!");
1238 
1239  if (MCL_OK != json_from_time_series_payload(&time_series->payload, &payload_string))
1240  {
1241  string_destroy(&store_data->meta);
1242  MCL_ERROR_RETURN(MCL_FAIL, "Get meta string from item meta for time_series has been failed!");
1243  }
1244  store_data->payload_buffer = (mcl_uint8_t *)payload_string->buffer;
1245  store_data->payload_size = payload_string->length;
1246 
1247  // Only buffer of the string_t is used as the payload. string_t object needs to be freed. We don't use string_destroy because it also frees the buffer which we don't want.
1248  MCL_FREE(payload_string);
1249  }
1250  else if (STORE_DATA_EVENT_LIST == store_data->type)
1251  {
1252  event_list_t *event_list;
1253  string_t *payload_string = MCL_NULL;
1254 
1255  MCL_DEBUG("Item type = <event>");
1256 
1257  event_list = (event_list_t *)store_data->data;
1258 
1259  // Generate the meta string :
1260  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(event_list->meta, &store_data->meta), MCL_FAIL, "Get meta string from item meta for event has been failed!");
1261 
1262  if (MCL_OK != json_from_event_payload(event_list->events, &payload_string))
1263  {
1264  string_destroy(&store_data->meta);
1265  MCL_ERROR_RETURN(MCL_FAIL, "Get meta string from item meta for event has been failed!");
1266  }
1267  store_data->payload_buffer = (mcl_uint8_t *)payload_string->buffer;
1268  store_data->payload_size = payload_string->length;
1269 
1270  // Only buffer of the string_t is used as the payload. string_t object needs to be freed. We don't use string_destroy because it also frees the buffer which we don't want.
1271  MCL_FREE(payload_string);
1272  }
1273  else if (STORE_DATA_FILE == store_data->type)
1274  {
1275  file_t *file;
1276 
1277  MCL_DEBUG("Item type = <file>");
1278 
1279  file = (file_t *)store_data->data;
1280 
1281  // Generate the meta string :
1282  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(&file->meta, &store_data->meta), MCL_FAIL, "Get meta string from item meta for file has been failed!");
1283 
1284  // Get file size.
1285  store_data->payload_size = file->payload.size;
1286  }
1287  else if (STORE_DATA_CUSTOM == store_data->type)
1288  {
1289  custom_data_t *custom_data;
1290 
1291  MCL_DEBUG("Item type = <custom_data>");
1292 
1293  custom_data = (custom_data_t *)store_data->data;
1294 
1295  // Generate the meta string :
1296  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(&custom_data->meta, &store_data->meta), MCL_FAIL, "Get meta string from item meta for custom_data has been failed!");
1297 
1298  // Custom data's payload will be its payload without any conversion :
1299  store_data->payload_buffer = custom_data->payload.buffer;
1300  store_data->payload_size = custom_data->payload.size;
1301  }
1302  else if (STORE_DATA_STREAM == store_data->type)
1303  {
1304  stream_data_t *stream_data;
1305 
1306  MCL_DEBUG("Item type = <stream_data>");
1307 
1308  stream_data = (stream_data_t *)store_data->data;
1309 
1310  // Generate the meta string :
1311  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(&stream_data->base->meta, &store_data->meta), MCL_FAIL,
1312  "Get meta string from item meta for custom_data has been failed!");
1313 
1314  // Its payload will be read from the callback.
1315  }
1316  else if (STORE_DATA_DATA_SOURCE_CONFIGURATION == store_data->type)
1317  {
1318  data_source_configuration_t *data_source_configuration;
1319  string_t *payload_string = MCL_NULL;
1320 
1321  MCL_DEBUG("Item type = <data_source_configuration>");
1322 
1323  data_source_configuration = (data_source_configuration_t *)store_data->data;
1324 
1325  // Generate the meta string :
1326  ASSERT_CODE_MESSAGE(MCL_OK == json_from_item_meta(&data_source_configuration->meta, &store_data->meta), MCL_FAIL, "Get meta string from item meta for data source configuration has been failed!");
1327 
1328  if (MCL_OK != json_from_data_source_configuration_payload(&data_source_configuration->payload, &payload_string))
1329  {
1330  string_destroy(&store_data->meta);
1331  MCL_ERROR_RETURN(MCL_FAIL, "Get meta string from item meta for data source configuration has been failed!");
1332  }
1333  store_data->payload_buffer = (mcl_uint8_t *)payload_string->buffer;
1334  store_data->payload_size = payload_string->length;
1335 
1336  // Only buffer of the string_t is used as the payload. string_t object needs to be freed. We don't use string_destroy because it also frees the buffer which we don't want.
1337  MCL_FREE(payload_string);
1338  }
1339 
1341 
1342  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
1343  return MCL_OK;
1344 }
1345 
1347 {
1348  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, store_t *store = <%p>, http_request_t *request = <%p>", http_processor, store, request)
1349 
1350  // With a main loop, function will try to add one item from the lists in store in every iteration.
1351  //
1352  // Loop will continue until no more suitable item left in the list.
1353  //
1354  // If current item in list couldn't be added because of no more space left in the request,
1355  // we continue trying to add next items in the list, since they might be added. And we iterate the current item which couldn't be added
1356  // to its next item in order to be able to try next item in the next iteration of the main loop.
1357  //
1358  // When getting the next item in the list, we are not using list_next() because it resets its current pointer
1359  // to the list_head if current points to the last element. This will cause same items to come up again
1360  // and cause infinite loops here(since current_item will never be NULL).
1361  //
1362  // We try to add an item to the request ( write it to the request ) only if that item isn't added before.
1363  // If add ( write ) operation is successful, _exchange_add_current_data_to_request() will set its write counter.
1364  //
1365  // Every item must be tried only once for adding to the current http_request
1366  // If they couldn't be added to the request, at some point current_item will point to the NULL which means
1367  // every item in the list is tried.
1368  //
1369  // In one iteration, if none of the items in the list is able to fit in the current request ( added_any == MCL_FALSE ), we break the loop.
1370  // There is no point to try any further in this case.
1371  //
1372 
1373  store_data_t *current_store_data = MCL_NULL;
1374 
1375  // Initialize with store empty code; if there won't be any suitable data found in store ( no data in Prepared ) or the store is actually empty,
1376  // this function will return MCL_STORE_IS_EMPTY.
1377 
1378  E_MCL_ERROR_CODE add_result;
1379  mcl_bool_t added_any = MCL_FALSE;
1380  mcl_bool_t added_any_at_all = MCL_FALSE;
1381 
1382  // TODO : Currently using only the high priority list
1383  list_t *current_list = store->high_priority_list;
1384 
1385  // Set current node to list's current node:
1386  list_node_t *current_list_node = current_list->current;
1387 
1388  MCL_DEBUG("Loop starting");
1389  do
1390  {
1391  if (MCL_NULL != current_list_node)
1392  {
1393  E_STORE_DATA_STATE state;
1394 
1395  current_store_data = (store_data_t *)current_list_node->data;
1396 
1397  // Prepare data ( Generate meta/payload strings ) if it is not already prepared.
1398  if (DATA_STATE_INITIAL == store_data_get_state(current_store_data))
1399  {
1400  ASSERT_CODE_MESSAGE(MCL_OK == _exchange_prepare_data(current_store_data), MCL_FAIL, "Generation of meta/payload buffers has been failed!");
1401  }
1402 
1403  // If data is not written already ( state == DATA_STATE_PREPARED ), try to add it :
1404  state = store_data_get_state(current_store_data);
1405  if ((DATA_STATE_PREPARED == state) || (DATA_STATE_STREAMING == state))
1406  {
1407  if (DATA_STATE_PREPARED == state)
1408  {
1409  add_result = _exchange_add_current_data_to_request(current_store_data, request);
1410  }
1411  else if (DATA_STATE_STREAMING == state)
1412  {
1413  add_result = _exchange_add_current_data_to_request_by_streaming(current_store_data, request);
1414  }
1415 
1416  // check result
1417  if ((MCL_OK == add_result) || (MCL_PARTIALLY_WRITTEN == add_result))
1418  {
1419  MCL_DEBUG("Current data has been added to the http request successfully. We continue to add for other items in the list.");
1420  added_any = MCL_TRUE;
1421  added_any_at_all = MCL_TRUE;
1422  }
1423  else if (MCL_HTTP_REQUEST_NO_MORE_SPACE == add_result)
1424  {
1425  MCL_DEBUG("There is not enough space left in the http request for current data.");
1426 
1427  // Check if we can stream this one. Or if it is already, continue.
1428  // If streaming is currently active; return right away to continue adding the same data w/o interrupting.
1429  // If not active; check if streaming is enabled and start if it is.
1430  if (DATA_STATE_STREAMING == store_data_get_state(current_store_data))
1431  {
1432  MCL_DEBUG("Streaming is already active for current data. Returning right away to write the rest.");
1433 
1436  }
1437  else if (MCL_TRUE == store->streamable)
1438  {
1439  MCL_DEBUG("Streaming is enabled. Streaming will be tried for this one.");
1440  store_data_set_state(current_store_data, DATA_STATE_STREAMING);
1441 
1442  // Because of this state, in the next iteration this data will be redirected to
1443  // _exchange_add_current_data_to_request_by_streaming() above.
1444  // ( current node won't be iterated to its next one. note the below check. )
1445 
1446  }
1447 
1448  // else : continue normal processing. No need for #else block.
1449  }
1450  else
1451  {
1452  MCL_DEBUG("Error response received from http request add operation. Aborting the operation!");
1453  break;
1454  }
1455  }
1456  else
1457  {
1458  MCL_DEBUG("Current data in the store is not in PREPARED state. Either it is not ready or it is already written. Skipping..");
1459  }
1460 
1461  // Iterate the list only if the current state of the data is not DATA_STATE_STREAMING
1462  // If it is, we need to stay on it until whole data is written
1463  if (DATA_STATE_STREAMING != store_data_get_state(current_store_data))
1464  {
1465  current_list_node = current_list_node->next;
1466  }
1467  else
1468  {
1469  MCL_DEBUG("Since streaming is active for current data, not iterating to the next store data.");
1470  }
1471  }
1472  else
1473  {
1474  MCL_DEBUG("End of list reached in the list.");
1475 
1476  // reached list end. If we didn't add anything since the last trip on the list; it means there is no data left in the list to add
1477  if (MCL_FALSE == added_any)
1478  {
1479  // In this iteration we tried till the NULL node and not any data could be added to the request
1480  // There is either no data left in the list or the no data is not suitable for the current
1481  // http request ( there must be not enough space left ). We can return now, no point in trying again :
1482  MCL_DEBUG("No item has been added to the request in this iteration. There is no suitable data in the store for the current request. Not going to try again.");
1483  break;
1484  }
1485  else
1486  {
1487  MCL_DEBUG("Some data has been added to the list in this iteration. We will try again from the beginning of the list. We might fit some more data.");
1488 
1489  // reset add flag :
1490  added_any = MCL_FALSE;
1491 
1492  // reset the current_list_node to the beginning of the list:
1493  current_list_node = current_list->head;
1494  }
1495  }
1496  }
1497  while (MCL_TRUE);
1498 
1499  MCL_DEBUG("Loop has ended.");
1500 
1501  if (MCL_FALSE == added_any_at_all)
1502  {
1503  MCL_DEBUG("Not any of the data in the store could be added to the request. There is no suitable data in it.");
1505  }
1506  else
1507  {
1508  MCL_DEBUG("Http request is ready to send. Finalizing..");
1509  add_result = _exchange_finalize_http_request(http_processor, request, MCL_FALSE);
1510  }
1511 
1512  DEBUG_LEAVE("retVal = <%d>", add_result);
1513  return add_result;
1514 }
1515 
1516 static E_MCL_ERROR_CODE _exchange_evaluate_response(store_t *store, E_MCL_ERROR_CODE send_result, http_response_t *response, void **reserved, string_t *correlation_id)
1517 {
1518  DEBUG_ENTRY("store_t *store = <%p>, E_MCL_ERROR_CODE send_result = <%d>, http_response_t *response = <%p>, void **reserved = <%p>, string_t *correlation_id = <%p>", store, send_result, response, reserved, correlation_id)
1519 
1520  E_MCL_ERROR_CODE result = MCL_FAIL;
1521 
1522  // Unused parameter.
1523  (void)reserved;
1524 
1525  if (MCL_OK == send_result)
1526  {
1527  if (MCL_NULL != response)
1528  {
1529  if (MCL_HTTP_RESULT_CODE_SUCCESS == response->result_code)
1530  {
1531  MCL_INFO("Send operation is successful. 200 OK Has been received from server. Correlation-ID = \"%s\"", correlation_id->buffer);
1532  result = MCL_OK;
1533  }
1534  else
1535  {
1536  // server did not respond OK.
1537  MCL_ERROR("Send operation is successful. ERROR code has been received from server = <%d>. Correlation-ID = \"%s\"", response->result_code, correlation_id->buffer);
1538  result = _evaluate_response_codes(response);
1539  }
1540 
1541  // TODO : Remove destroying the response if evaluation needs it to be used somewhere else in the future:
1542  // response is not necessary currently.
1543  http_response_destroy(&response);
1544  }
1545  else
1546  {
1547  MCL_DEBUG("HTTP response object is NULL. Means the send operation is failed!");
1548  }
1549  }
1550  else
1551  {
1552  MCL_DEBUG("Send result is not successful.");
1553  result = send_result;
1554  }
1555 
1556  // Update the store data states according to the result of send operation :
1557  if (MCL_OK == result)
1558  {
1561  }
1562  else
1563  {
1565  }
1566 
1567  DEBUG_LEAVE("retVal = <%d>", result);
1568  return result;
1569 }
1570 
1571 static E_MCL_ERROR_CODE _exchange_update_store_data_state(store_data_t *store_data, mcl_bool_t send_operation_successful)
1572 {
1573  DEBUG_ENTRY("store_data_t *store_data = <%p>, mcl_bool_t send_operation_successful = <%u>", store_data, send_operation_successful)
1574 
1575  E_STORE_DATA_STATE state = store_data_get_state(store_data);
1576 
1577  if (DATA_STATE_WRITTEN == state)
1578  {
1579  if (MCL_TRUE == send_operation_successful)
1580  {
1581  // data has been sent. go to next state :
1583  }
1584  else
1585  {
1586  // data couldn't be sent. go to previous state. do necessary arrangements :
1588  }
1589  }
1590  else
1591  {
1592  // no need to update the state
1593  MCL_DEBUG("State is %d, no need to update current items state", state);
1594  }
1595 
1596  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
1597  return MCL_OK;
1598 }
1599 
1600 static E_MCL_ERROR_CODE _exchange_update_store_state(store_t *store, mcl_bool_t send_operation_successful)
1601 {
1602  DEBUG_ENTRY("store_t *store = <%p>, mcl_bool_t send_operation_successful = <%u>", store, send_operation_successful)
1603 
1604  list_node_t *current_node = MCL_NULL;
1605 
1607  list_reset(store->low_priority_list);
1608 
1609  // high_priority_list
1610  while (MCL_NULL != (current_node = list_next(store->high_priority_list)))
1611  {
1612  _exchange_update_store_data_state((store_data_t *)current_node->data, send_operation_successful);
1613  }
1614 
1615  // low_priority_list
1616  while (MCL_NULL != (current_node = list_next(store->low_priority_list)))
1617  {
1618  _exchange_update_store_data_state((store_data_t *)current_node->data, send_operation_successful);
1619  }
1620 
1621  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
1622  return MCL_OK;
1623 }
1624 
1626 {
1627  DEBUG_ENTRY("store_t *store = <%p>", store)
1628 
1629  // in every store_data item, remove the item if its state is sent
1630  list_node_t *current_node = MCL_NULL;
1631 
1632  // high priority list
1633  while (MCL_NULL != (current_node = list_next(store->high_priority_list)))
1634  {
1635  if (DATA_STATE_SENT == store_data_get_state((store_data_t *)current_node->data))
1636  {
1637  store_data_remove(store->high_priority_list, current_node);
1638  }
1639  }
1640 
1641  // low priority list
1642  while (MCL_NULL != (current_node = list_next(store->low_priority_list)))
1643  {
1644  if (DATA_STATE_SENT == store_data_get_state((store_data_t *)current_node->data))
1645  {
1646  store_data_remove(store->low_priority_list, current_node);
1647  }
1648  }
1649 
1650  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
1651  return MCL_OK;
1652 }
1653 
1654 static E_MCL_ERROR_CODE _exchange_store_data_get_content_info(store_data_t *store_data, string_t **meta_content_type, string_t **meta_content_id,
1655  string_t **payload_content_type)
1656 {
1657  DEBUG_ENTRY("store_data_t *store_data = <%p>, string_t *meta_content_type = <%p>, string_t *meta_content_id = <%p>, string_t *payload_content_type = <%p>", store_data,
1658  meta_content_type, meta_content_id, payload_content_type)
1659 
1660  E_MCL_ERROR_CODE result = MCL_OK;
1661 
1662  // generate the meta/payload string based on the type:
1663  if (STORE_DATA_TIME_SERIES == store_data->type)
1664  {
1665  time_series_t *time_series;
1666 
1667  MCL_DEBUG("Item type = <time_series>");
1668  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1669  *payload_content_type = &content_type_values[CONTENT_TYPE_APPLICATION_JSON];
1670 
1671  time_series = (time_series_t *)store_data->data;
1672  *meta_content_id = time_series->meta.content_id;
1673  }
1674  else if (STORE_DATA_EVENT_LIST == store_data->type)
1675  {
1676  event_list_t *event_list;
1677 
1678  MCL_DEBUG("Item type = <event>");
1679  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1680  *payload_content_type = &content_type_values[CONTENT_TYPE_APPLICATION_JSON];
1681 
1682  event_list = (event_list_t *)store_data->data;
1683  *meta_content_id = event_list->meta->content_id;
1684  }
1685  else if (STORE_DATA_FILE == store_data->type)
1686  {
1687  file_t *file;
1688  MCL_DEBUG("Item type = <file>");
1689  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1691 
1692  file = (file_t *)store_data->data;
1693  *meta_content_id = file->meta.content_id;
1694  }
1695  else if (STORE_DATA_CUSTOM == store_data->type)
1696  {
1697  custom_data_t *custom_data;
1698  MCL_DEBUG("Item type = <custom_data>");
1699  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1701 
1702  custom_data = (custom_data_t *)store_data->data;
1703  *meta_content_id = custom_data->meta.content_id;
1704 
1705  }
1706  else if (STORE_DATA_STREAM == store_data->type)
1707  {
1708  custom_data_t *custom_data;
1709 
1710  MCL_DEBUG("Item type = <stream_data>");
1711  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1713 
1714  custom_data = ((stream_data_t *)store_data->data)->base;
1715  *meta_content_id = custom_data->meta.content_id;
1716  }
1717  else if (STORE_DATA_DATA_SOURCE_CONFIGURATION == store_data->type)
1718  {
1719  data_source_configuration_t *data_source_configuration;
1720 
1721  MCL_DEBUG("Item type = <data_source_configuration>");
1722  *meta_content_type = &content_type_values[CONTENT_TYPE_META_JSON];
1723  *payload_content_type = &content_type_values[CONTENT_TYPE_APPLICATION_JSON];
1724 
1725  data_source_configuration = (data_source_configuration_t *)store_data->data;
1726  *meta_content_id = data_source_configuration->meta.content_id;
1727  }
1728  else
1729  {
1730  MCL_DEBUG("Item type = <UNKNOWN(%d)>", store_data->type);
1731  result = MCL_FAIL;
1732 
1733  *meta_content_type = MCL_NULL;
1734  *meta_content_id = MCL_NULL;
1735  *payload_content_type = MCL_NULL;
1736  }
1737 
1738  DEBUG_LEAVE("retVal = <%d>", result);
1739  return result;
1740 }
1741 
1743 {
1744  DEBUG_ENTRY("http_request_t *request = <%p>", request)
1745 
1746  // Add these headers :
1747  // 1- Content-type
1748  // 2- If with_authentication is true : Authentication header
1749  // 2- Else; Authentication header will be included at the end
1750 
1752  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Add header to request has been failed for <Content-Type>.");
1753 
1755  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Add header to request has been failed for <Accept>.");
1756 
1757  ASSERT_CODE(MCL_OK == _add_authentication_header_to_request(http_processor, request, with_authentication), MCL_HTTP_REQUEST_FINALIZE_FAILED);
1758 
1759  DEBUG_LEAVE("retVal = <%d>", result);
1760  return result;
1761 }
1762 
1764 {
1765  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, http_request_t *request = <%p>", http_processor, request)
1766 
1767  // finalize the http_request
1768  E_MCL_ERROR_CODE result = http_request_finalize(request);
1769  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "http request finalize is failed!");
1770 
1771  ASSERT_CODE(MCL_OK == _add_authentication_header_to_request(http_processor, request, with_authentication), MCL_HTTP_REQUEST_FINALIZE_FAILED);
1772 
1773  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
1774  return MCL_OK;
1775 }
1776 
1778 {
1779  if (MCL_TRUE == with_authentication)
1780  {
1781  // Add "Bearer" in front of JWT string.
1782  string_t *bearer = MCL_NULL;
1783  string_t *jwt_string = MCL_NULL;
1784  E_MCL_ERROR_CODE code = string_initialize_static("Bearer ", 0, &bearer);
1785  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "Bearer string can not be created.");
1786 
1787  code = string_concatenate(bearer, http_processor->security_handler->access_token, &jwt_string);
1788  string_destroy(&bearer);
1789  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "Bearer string can not be added to JWT string.");
1790 
1792  string_destroy(&jwt_string);
1793  ASSERT_CODE_MESSAGE(MCL_OK == code, MCL_HTTP_REQUEST_FINALIZE_FAILED, "Add header to request has been failed for <Authorization>.");
1794  }
1795 
1796  return MCL_OK;
1797 }
1798 
1799 static mcl_size_t _get_payload_from_buffer(void *destination, void *source, mcl_size_t size, void *user_context)
1800 {
1801  DEBUG_ENTRY("void *destination = <%p>, void *source = <%p>, mcl_size_t size = <%u>, void *user_context = <%p>", destination, source, size, user_context)
1802 
1803  // Unused parameter.
1804  (void)user_context;
1805 
1806  string_util_memcpy(destination, source, size);
1807 
1808  DEBUG_LEAVE("retVal = <%u>", size);
1809  return size;
1810 }
1811 
1812 static mcl_size_t _get_payload_from_file(void *destination, void *file_descriptor, mcl_size_t size, void *user_context)
1813 {
1814  DEBUG_ENTRY("void *destination = <%p>, void *file_descriptor = <%p>, mcl_size_t size = <%u>, void *user_context = <%p>", destination, file_descriptor, size, user_context)
1815 
1816  mcl_size_t actual_size_read = 0;
1817 
1818  // Unused parameter.
1819  (void)user_context;
1820 
1821  file_util_fread(destination, 1, size, file_descriptor, &actual_size_read);
1822 
1823  DEBUG_LEAVE("retVal = <%u>", actual_size_read);
1824  return actual_size_read;
1825 }
1826 
1827 #if MCL_STREAM_ENABLED
1828 mcl_size_t _stream_callback(void *buffer, mcl_size_t size, mcl_size_t count, void *user_context)
1829 {
1830  DEBUG_ENTRY("void *buffer = <%p>, mcl_size_t size = <%u>, mcl_size_t count = <%u>, void *user_context = <%p>", buffer, size, count, user_context)
1831 
1832  // get http_request and store data from user context:
1833  http_processor_stream_callback_context_t *http_processor_callback_context = (http_processor_stream_callback_context_t *)user_context;
1834  http_processor_t *http_processor = http_processor_callback_context->http_processor;
1835  http_request_t *request = http_processor_callback_context->request;
1836  store_t *store = http_processor_callback_context->store;
1837  E_MCL_ERROR_CODE previous_result = http_processor_callback_context->previous_result;
1838 
1839  mcl_size_t written = 0;
1840 
1841  // Check if max call count is reached. Do not terminate if we are in the middle of something even if tha max call count is reached.
1842  if ((MAX_STREAM_CALLBACK_CALL_COUNT > http_processor_callback_context->call_count) || (MCL_EXCHANGE_STREAMING_IS_ACTIVE == previous_result)
1843  || (MCL_HTTP_REQUEST_FINALIZE_FAILED == previous_result))
1844  {
1845  request->payload = buffer;
1846  request->payload_size = size * count;
1847  request->payload_offset = 0;
1848 
1849  E_MCL_ERROR_CODE result;
1850 
1851  // If only finalize is failed last time, lets try it again:
1852  if (MCL_HTTP_REQUEST_FINALIZE_FAILED == previous_result)
1853  {
1854  result = _exchange_finalize_http_request(http_processor, request, MCL_FALSE);
1855 
1856  // if it is failed again, just give up
1857  if (MCL_OK != result)
1858  {
1859  MCL_DEBUG("Second try of http_request_finalize is failed again! Terminating the operation.");
1860  result = MCL_FAIL;
1861  }
1862  }
1863  else
1864  {
1865  result = _exchange_fill_http_request(http_processor, store, request);
1866  }
1867 
1868  // Check the result :
1869  if ((MCL_OK == result) || (MCL_HTTP_REQUEST_FINALIZE_FAILED == result) || (MCL_STORE_IS_EMPTY == result) || (MCL_EXCHANGE_STREAMING_IS_ACTIVE == result) || (MCL_STORE_ITEM_EXCEEDS_MAX_HTTP_REQUEST_SIZE == result))
1870  {
1871  // If MCL_HTTP_REQUEST_FINALIZE_FAILED, let's return the current written amount and try for finalize in the next call.
1872 
1873  // If MCL_STORE_IS_EMPTY, payload_offset must be 0, just return it to end the send operation.
1874 
1875  // If MCL_EXCHANGE_STREAMING_IS_ACTIVE: We are still in the middle of something. Just continue ..
1876 
1877  // if this will be 0 callback will be terminated. Not checking.
1878  written = request->payload_offset;
1879  }
1880  else
1881  {
1882  MCL_DEBUG("Fill http request operation is failed. Terminating send operation.");
1883 
1884  // Get actual terminating error code from http_client.
1886  }
1887 
1888  // save result in order to be used in next call ( if there will be ):
1889  MCL_DEBUG("Fill operation result will be saved to be used in next call = <%u>.", result);
1890  http_processor_callback_context->previous_result = result;
1891 
1892  // reset the request :
1893  request->payload = MCL_NULL;
1894  request->payload_size = 0;
1895  request->payload_offset = 0;
1896  }
1897  else
1898  {
1899  MCL_DEBUG("Max callback call limit has been reached. Call count = <%d>. Terminating the send operation.", http_processor_callback_context->call_count);
1900  written = 0;
1901  }
1902 
1903  http_processor_callback_context->call_count++;
1904 
1905  DEBUG_LEAVE("retVal = <%u>", written);
1906  return written;
1907 }
1908 #endif
1909 
1911 {
1912  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, http_response_t *http_response = <%p>", http_processor, http_response)
1913 
1914  json_t *json_root = MCL_NULL;
1915  json_t *client_id = MCL_NULL;
1916  json_t *client_secret = MCL_NULL;
1917  json_t *registration_access_token = MCL_NULL;
1918  json_t *registration_client_uri = MCL_NULL;
1919  mcl_bool_t ok;
1920 
1921  E_MCL_ERROR_CODE code = json_util_parse_with_size((char *)http_response_get_payload(http_response), http_response->payload_size, &json_root);
1922  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "parsing payload of http_response failed.");
1923 
1924  ok = MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_CLIENT_ID, &client_id));
1925  ok = ok && (MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_CLIENT_SECRET, &client_secret)));
1926  ok = ok && (MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_REGISTRATION_ACCESS_TOKEN, &registration_access_token)));
1927  ok = ok && (MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_REGISTRATION_CLIENT_URI, &registration_client_uri)));
1928 
1929  if (ok)
1930  {
1931  string_destroy(&http_processor->security_handler->client_id);
1932  string_destroy(&http_processor->security_handler->client_secret);
1935 
1936  ok = ok && (MCL_OK == (code = json_util_get_string(client_id, &http_processor->security_handler->client_id)));
1937  ok = ok && (MCL_OK == (code = json_util_get_string(client_secret, &http_processor->security_handler->client_secret)));
1938  ok = ok && (MCL_OK == (code = json_util_get_string(registration_access_token, &http_processor->security_handler->registration_access_token)));
1939  ok = ok && (MCL_OK == (code = json_util_get_string(registration_client_uri, &http_processor->security_handler->registration_client_uri)));
1940 
1941  if (!ok)
1942  {
1943  string_destroy(&http_processor->security_handler->client_id);
1944  string_destroy(&http_processor->security_handler->client_secret);
1947  }
1948  }
1949 
1950  // Child json objects are reference to their parts in root json. So we only free the struct.
1951  MCL_FREE(client_id);
1952  MCL_FREE(client_secret);
1953  MCL_FREE(registration_access_token);
1954  MCL_FREE(registration_client_uri);
1955  json_util_destroy(&json_root);
1956 
1957  DEBUG_LEAVE("retVal = <%d>", code);
1958  return code;
1959 }
1960 
1962 {
1963  DEBUG_ENTRY("http_processor_t *http_processor = <%p>, http_response_t *http_response = <%p>", http_processor, http_response)
1964 
1965  json_t *json_root = MCL_NULL;
1966  json_t *client_id = MCL_NULL;
1967  json_t *registration_access_token = MCL_NULL;
1968  json_t *registration_client_uri = MCL_NULL;
1969  mcl_bool_t ok;
1970 
1971  E_MCL_ERROR_CODE code = json_util_parse_with_size((char *)http_response_get_payload(http_response), http_response->payload_size, &json_root);
1972  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "parsing payload of http_response failed.");
1973 
1974  ok = MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_CLIENT_ID, &client_id));
1975  ok = ok && (MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_REGISTRATION_ACCESS_TOKEN, &registration_access_token)));
1976  ok = ok && (MCL_OK == (code = json_util_get_object_item(json_root, JSON_NAME_REGISTRATION_CLIENT_URI, &registration_client_uri)));
1977 
1978  if (ok)
1979  {
1980  string_destroy(&http_processor->security_handler->client_id);
1983 
1984  ok = ok && (MCL_OK == (code = json_util_get_string(client_id, &http_processor->security_handler->client_id)));
1985  ok = ok && (MCL_OK == (code = json_util_get_string(registration_access_token, &http_processor->security_handler->registration_access_token)));
1986  ok = ok && (MCL_OK == (code = json_util_get_string(registration_client_uri, &http_processor->security_handler->registration_client_uri)));
1987 
1988  if (!ok)
1989  {
1990  string_destroy(&http_processor->security_handler->client_id);
1993  }
1994  }
1995 
1996  // Child json objects are reference to their parts in root json. So we only free the struct.
1997  MCL_FREE(client_id);
1998  MCL_FREE(registration_access_token);
1999  MCL_FREE(registration_client_uri);
2000  json_util_destroy(&json_root);
2001 
2002  DEBUG_LEAVE("retVal = <%d>", code);
2003  return code;
2004 }
2005 
2006 #if MCL_FILE_DOWNLOAD_ENABLED
2007 static E_MCL_ERROR_CODE _get_file_name(char *header, string_t **file_name)
2008 {
2009  DEBUG_ENTRY("char *header = <%p>, char **file_name = <%p>", header, file_name)
2010 
2011  /*
2012  File name is present in header "Content-Disposition" in following format.
2013 
2014  Content-Disposition: attachment; filename="<filename>"
2015 
2016  We try to find two quotes after "filename" keyword and then the file name in between.
2017  */
2018 
2019  char *file_name_keyword = "filename";
2020  mcl_size_t file_name_keyword_length = 9;
2021 
2022  mcl_size_t file_name_index;
2023  mcl_bool_t file_name_found = string_util_find(header, file_name_keyword, &file_name_index);
2024  ASSERT_CODE_MESSAGE(MCL_TRUE == file_name_found, MCL_FAIL, "Could not find filename keyword in header.");
2025 
2026  // Add length of the keyword to it's start index.
2027  file_name_index += file_name_keyword_length;
2028 
2029  // Find first quote
2030  mcl_size_t first_quote_index;
2031  mcl_bool_t first_quote_found = string_util_find(header + file_name_index, "\"", &first_quote_index);
2032  ASSERT_CODE_MESSAGE(MCL_TRUE == first_quote_found, MCL_FAIL, "Could not find second header in header.");
2033 
2034  first_quote_index += file_name_index;
2035 
2036  mcl_size_t second_quote_index;
2037  mcl_bool_t second_quote_found = string_util_find(header + first_quote_index + 1, "\"", &second_quote_index);
2038  ASSERT_CODE_MESSAGE(MCL_TRUE == second_quote_found, MCL_FAIL, "Could not find second header in header.");
2039 
2040  mcl_size_t file_name_size = (second_quote_index + 1);
2041  char *file_name_local = MCL_MALLOC(file_name_size + 1);
2042 
2043  ASSERT_CODE(MCL_NULL != file_name_local, MCL_OUT_OF_MEMORY);
2044 
2045  string_util_strncpy(file_name_local, header + first_quote_index + 1, file_name_size);
2046  file_name_local[file_name_size] = MCL_NULL_CHAR;
2047 
2048  string_initialize_dynamic(file_name_local, 0, file_name);
2049 
2050  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
2051  return MCL_OK;
2052 }
2053 #endif
2054 
2055 #if MCL_FILE_DOWNLOAD_ENABLED
2056 static E_MCL_ERROR_CODE _add_range_header(http_request_t *request, mcl_size_t start_byte, mcl_size_t end_byte)
2057 {
2058  DEBUG_ENTRY("http_request_t *request = <%p>, mcl_size_t start_byte = <%u>, mcl_size_t end_byte = <%u>", request, start_byte, end_byte)
2059 
2060  char temp_header_value[MAX_RANGE_HEADER_LENGTH] = { 0 };
2061 
2062  E_MCL_ERROR_CODE result = string_util_snprintf(temp_header_value, MAX_RANGE_HEADER_LENGTH, "bytes=%u-%u", start_byte, end_byte);
2063  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "string_util_snprintf() failed for start_byte <%u> and end_byte <%u>", start_byte, end_byte);
2064 
2065  string_t *range_header_value = MCL_NULL;
2066  result = string_initialize_new(temp_header_value, 0, &range_header_value);
2067  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Memory cannot be allocated for Range header value.");
2068 
2069  result = http_request_add_header(request, &http_header_names[HTTP_HEADER_RANGE], range_header_value);
2070  string_destroy(&range_header_value);
2071  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Could not add Range header to request.");
2072 
2073  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
2074  return MCL_OK;
2075 }
2076 
2077 static E_MCL_ERROR_CODE _add_actual_range_to_file(http_response_t *response, file_t *file)
2078 {
2079  DEBUG_ENTRY("http_response_t *response = <%p>, mcl_file_t *file = <%p>", response, file)
2080 
2081  string_t *content_range_header = MCL_NULL;
2082  E_MCL_ERROR_CODE result = http_response_get_header(response, http_header_names[HTTP_HEADER_CONTENT_RANGE].buffer, &content_range_header);
2083  ASSERT_CODE_MESSAGE(MCL_OK == result, result, "Could not get header.");
2084 
2085  // Find first integral value
2086  char *rest = MCL_NULL;
2087  char *rest2 = MCL_NULL;
2088 
2089  char *string = content_range_header->buffer;
2090 
2091  // Skip until the current character is a digit (i.e. it's value is between ASCII value of 0 and 9 inclusive)
2092  while (!((47 < *string) && (58 > *string)))
2093  {
2094  // If null termination is reached then break
2095  if (0 == *string)
2096  {
2097  break;
2098  }
2099  ++string;
2100  }
2101 
2102  mcl_size_t start_byte = string_util_strtol(string, 10, &rest);
2103  ASSERT_STATEMENT_CODE_MESSAGE(MCL_NULL != rest, string_destroy(&content_range_header), MCL_FAIL, "string_util_strtol() failed for %s", string);
2104 
2105  while (!((47 < *rest) && (58 > *rest)))
2106  {
2107  if (0 == *rest)
2108  {
2109  break;
2110  }
2111  ++rest;
2112  }
2113  mcl_size_t end_byte = string_util_strtol(rest, 10, &rest2);
2114  string_destroy(&content_range_header);
2115  ASSERT_CODE_MESSAGE((MCL_NULL != rest2) && (rest2 != rest), MCL_FAIL, "string_util_strtol() failed");
2116 
2117  file->payload.start_byte = start_byte;
2118  file->payload.end_byte = end_byte;
2119 
2120  DEBUG_LEAVE("retVal = <%d>", MCL_OK);
2121  return MCL_OK;
2122 }
2123 #endif
2124 
2126 {
2127  DEBUG_ENTRY("security_handler_t *security_handler = <%p>, string_t **payload = <%p>", security_handler, payload)
2128 
2129  json_t *root = MCL_NULL;
2130  json_t *jwks = MCL_NULL;
2131  json_t *keys = MCL_NULL;
2132  json_t *key_1 = MCL_NULL;
2133 
2134  char *modulus = MCL_NULL;
2135  char *public_exponent = MCL_NULL;
2136  char *payload_string = MCL_NULL;
2137 
2138  E_MCL_ERROR_CODE code = security_rsa_get_modulus_and_exponent(security_handler->rsa.public_key, &modulus, &public_exponent);
2139 
2140  (MCL_OK == code) && (code = json_util_initialize(JSON_OBJECT, &root));
2141  (MCL_OK == code) && (code = json_util_start_object(root, JSON_NAME_JWKS, &jwks));
2142  (MCL_OK == code) && (code = json_util_start_array(jwks, JSON_NAME_KEYS, &keys));
2143  (MCL_OK == code) && (code = _add_key_to_keys_array(keys, &key_1));
2144  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_E, public_exponent));
2145  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_N, modulus));
2146  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_KTY, "RSA"));
2147  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_KID, "key-1"));
2148  (MCL_OK == code) && (code = json_util_to_string(root, &payload_string));
2149  (MCL_OK == code) && (code = string_initialize_dynamic(payload_string, 0, payload));
2150 
2151  if (MCL_OK != code)
2152  {
2153  MCL_FREE(payload_string);
2154  }
2155 
2156  MCL_FREE(modulus);
2157  MCL_FREE(public_exponent);
2158  json_util_finish_object(&key_1);
2159  json_util_finish_object(&keys);
2160  json_util_finish_object(&jwks);
2161  json_util_destroy(&root);
2162 
2163  DEBUG_LEAVE("retVal = <%d>", code);
2164  return code;
2165 }
2166 
2168 {
2169  DEBUG_ENTRY("security_handler_t *security_handler = <%p>, string_t **payload = <%p>", security_handler, payload)
2170 
2171  E_MCL_ERROR_CODE code;
2172  json_t *root = MCL_NULL;
2173  json_t *jwks = MCL_NULL;
2174  json_t *keys = MCL_NULL;
2175  json_t *key_1 = MCL_NULL;
2176 
2177  char *modulus = MCL_NULL;
2178  char *public_exponent = MCL_NULL;
2179  char *payload_string = MCL_NULL;
2180 
2181  MCL_FREE(security_handler->rsa.public_key);
2182  MCL_FREE(security_handler->rsa.private_key);
2183  code = security_handler_generate_rsa_key(security_handler);
2184 
2185  (MCL_OK == code) && (code = security_rsa_get_modulus_and_exponent(security_handler->rsa.public_key, &modulus, &public_exponent));
2186  (MCL_OK == code) && (code = json_util_initialize(JSON_OBJECT, &root));
2187  (MCL_OK == code) && (code = json_util_add_string(root, JSON_NAME_CLIENT_ID, security_handler->client_id->buffer));
2188  (MCL_OK == code) && (code = json_util_start_object(root, JSON_NAME_JWKS, &jwks));
2189  (MCL_OK == code) && (code = json_util_start_array(jwks, JSON_NAME_KEYS, &keys));
2190  (MCL_OK == code) && (code = _add_key_to_keys_array(keys, &key_1));
2191  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_E, public_exponent));
2192  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_N, modulus));
2193  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_KTY, "RSA"));
2194  (MCL_OK == code) && (code = json_util_add_string(key_1, JSON_NAME_KID, "key-1"));
2195  (MCL_OK == code) && (code = json_util_to_string(root, &payload_string));
2196  (MCL_OK == code) && (code = string_initialize_dynamic(payload_string, 0, payload));
2197 
2198  if (MCL_OK != code)
2199  {
2200  MCL_FREE(payload_string);
2201  }
2202 
2203  MCL_FREE(modulus);
2204  MCL_FREE(public_exponent);
2205  json_util_finish_object(&key_1);
2206  json_util_finish_object(&keys);
2207  json_util_finish_object(&jwks);
2208  json_util_destroy(&root);
2209 
2210  DEBUG_LEAVE("retVal = <%d>", code);
2211  return code;
2212 }
2213 
2215 {
2216  DEBUG_ENTRY("json_t *root = <%p>, json_t **json_object = <%p>", root, json_object)
2217 
2218  E_MCL_ERROR_CODE code = json_util_initialize(JSON_OBJECT, json_object);
2219  ASSERT_CODE_MESSAGE(MCL_OK == code, code, "json_object couldn't be allocated in memory.");
2220 
2221  json_util_add_item_to_array(root, *json_object);
2222 
2223  DEBUG_LEAVE("retVal = <%d>", code);
2224  return code;
2225 }
2226 
2227 static E_MCL_ERROR_CODE _check_file_path(const char *file_name)
2228 {
2229  DEBUG_ENTRY("const char *file_name = <%p>", file_name)
2230 
2231  void *file_descriptor = MCL_NULL;
2232  E_MCL_ERROR_CODE code = file_util_fopen(file_name, "a", &file_descriptor);
2233 
2234  if (MCL_OK == code)
2235  {
2236  file_util_fclose(file_descriptor);
2237  }
2238 
2239  DEBUG_LEAVE("retVal = <%d>", code);
2240  return code;
2241 }
2242 
2244 {
2245  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
2246 
2247  E_MCL_ERROR_CODE code;
2248  char *client_id;
2249  char *registration_access_token;
2250  char *registration_uri;
2251 
2253  {
2254  char *client_secret;
2255  code = http_processor->configuration->load_function.shared_secret(&client_id, &client_secret, &registration_access_token, &registration_uri);
2256 
2257  if(MCL_OK == code)
2258  {
2259  string_initialize_dynamic(client_secret, 0, &(http_processor->security_handler->client_secret));
2260  }
2261  }
2262  else
2263  {
2264  code = http_processor->configuration->load_function.rsa(&client_id, &(http_processor->security_handler->rsa.public_key), &(http_processor->security_handler->rsa.private_key), &registration_access_token, &registration_uri);
2265  }
2266 
2267  if(MCL_OK == code)
2268  {
2269  string_initialize_dynamic(client_id, 0, &(http_processor->security_handler->client_id));
2270  string_initialize_dynamic(registration_access_token, 0, &(http_processor->security_handler->registration_access_token));
2271  string_initialize_dynamic(registration_uri, 0, &(http_processor->security_handler->registration_client_uri));
2272  }
2273 
2274  DEBUG_LEAVE("retVal = <%d>", code);
2275  return code;
2276 }
2277 
2279 {
2280  DEBUG_ENTRY("http_response_t *response = <%p>", response)
2281 
2282  E_MCL_ERROR_CODE code;
2283  switch (response->result_code)
2284  {
2286  code = MCL_OK;
2287  break;
2288 
2290  code = MCL_CREATED;
2291  break;
2292 
2294  code = MCL_PARTIAL_CONTENT;
2295  break;
2296 
2298  code = MCL_BAD_REQUEST;
2299  break;
2300 
2302  code = MCL_UNAUTHORIZED;
2303  break;
2304 
2306  code = MCL_FORBIDDEN;
2307  break;
2308 
2310  code = MCL_NOT_FOUND;
2311  break;
2312 
2314  code = MCL_SERVER_FAIL;
2315  break;
2316 
2318  code = MCL_CONFLICT;
2319  break;
2320 
2322  code = MCL_PRECONDITION_FAIL;
2323  break;
2324 
2327  break;
2328 
2330  code = MCL_TOO_MANY_REQUESTS;
2331  break;
2332 
2333  default :
2335  MCL_INFO("Server responded with unexpected HTTP status code %d.", response->result_code);
2336  break;
2337  }
2338 
2339  DEBUG_LEAVE("retVal = <%d>", code);
2340  return code;
2341 }
2342 
2344 {
2345  DEBUG_ENTRY("string_t **correlation_id = <%p>", correlation_id)
2346 
2347  mcl_uint16_t index;
2348  uint8_t random_bytes[CORRELATION_ID_BYTE_LENGTH] = {0};
2350 
2351  ASSERT_CODE(MCL_OK == code, code);
2352  code = string_initialize_new(MCL_NULL, CORRELATION_ID_BYTE_LENGTH * 2, correlation_id);
2353 
2354  ASSERT_CODE(MCL_OK == code, code);
2355 
2356  for(index = 0; index < CORRELATION_ID_BYTE_LENGTH; index++)
2357  {
2358  code = string_util_snprintf(&((*correlation_id)->buffer[index * 2]), 3, "%02x", random_bytes[index]);
2359  ASSERT_STATEMENT_CODE(MCL_OK == code, string_destroy(correlation_id), code);
2360  }
2361 
2362  DEBUG_LEAVE("retVal = <%d>", code);
2363  return code;
2364 }
2365 
2367 {
2368  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
2369 
2370  // Set default error code to MCL_OK assuming if no storage option is provided agent does not want to save data.
2371  E_MCL_ERROR_CODE result = MCL_OK;
2372 
2373  // Store registration information via custom functions if both function pointers are not null.
2374  if(MCL_NULL != http_processor->configuration->load_function.rsa && MCL_NULL != http_processor->configuration->save_function.rsa)
2375  {
2377  {
2379  }
2380  else
2381  {
2382  result = http_processor->configuration->save_function.rsa(http_processor->security_handler->client_id->buffer, (char *)http_processor->security_handler->rsa.public_key, (char *)http_processor->security_handler->rsa.private_key, http_processor->security_handler->registration_access_token->buffer, http_processor->security_handler->registration_client_uri->buffer);
2383  }
2384  }
2385  // Store registration information via file system if a storage path is provided.
2386  else if (MCL_NULL != http_processor->configuration->store_path)
2387  {
2389  {
2391  http_processor->security_handler->client_secret, http_processor->security_handler->registration_access_token,
2392  http_processor->security_handler->registration_client_uri);
2393  }
2394  else
2395  {
2397  (char *)http_processor->security_handler->rsa.public_key, (char *)http_processor->security_handler->rsa.private_key,
2399  }
2400  }
2401 
2402  DEBUG_LEAVE("retVal = <%d>", result);
2403  return result;
2404 }
2405 
2407 {
2408  DEBUG_ENTRY("http_processor_t *http_processor = <%p>", http_processor)
2409 
2410  E_MCL_ERROR_CODE code;
2411  jwt_t *jwt = MCL_NULL;
2412  string_t *jwt_string = MCL_NULL;
2413  string_t *request_payload_head = MCL_NULL;
2414  const char *head = "grant_type=client_credentials&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=";
2415 
2416  // Create a new self issued jwt.
2417  code = jwt_initialize(http_processor->security_handler, http_processor->configuration->security_profile, http_processor->configuration->tenant, &jwt);
2418 
2419  // Compose jwt string.
2420  if (MCL_OK == code)
2421  {
2422  jwt_string = jwt_get_token(jwt);
2423  jwt_destroy(&jwt);
2424  if (MCL_NULL == jwt_string)
2425  {
2426  code = MCL_FAIL;
2427  }
2428  }
2429 
2430  // Set the constant part of request payload.
2431  (MCL_OK == code) && (code = string_initialize_static(head, 0, &request_payload_head));
2432 
2433  // Form the final request payload.
2434  (MCL_OK == code) && (code = string_concatenate(request_payload_head, jwt_string, request_payload));
2435  string_destroy(&request_payload_head);
2436  string_destroy(&jwt_string);
2437 
2438  DEBUG_LEAVE("retVal = <%d>", code);
2439  return code;
2440 }
Content type is application octet stream.
Definition: data_types.h:314
HTTP definitions module header file.
HTTP Request Handle.
Definition: http_request.h:79
store_data_stream_info_t * stream_info
Stream information.
Definition: store.h:71
#define JSON_NAME_KID
list_t * events
Payload of event list.
Definition: event_list.h:28
item_meta_t meta
Meta of custom data.
Definition: custom_data.h:26
static E_MCL_ERROR_CODE _compose_rsa_key_rotation_json(security_handler_t *security_handler, string_t **payload)
static E_MCL_ERROR_CODE _exchange_update_store_state(store_t *store, mcl_bool_t send_operation_successful)
mcl_load_rsa_callback_t rsa
Callback type to load RSA key.
Definition: mcl_common.h:297
void string_destroy(string_t **string)
Destroys the allocated resources of the string.
Definition: string_type.c:326
http_client_t * http_client
Http client handler.
Data source configuration module header file.
Http accept header.
Internal failure in MCL.
Definition: mcl_common.h:141
Memory module header file.
long string_util_strtol(const char *source, int base, char **end_pointer)
Returns the first occurrence of an integral value in source string.
Definition: string_util.c:232
#define JSON_NAME_ACCESS_TOKEN
E_MCL_ERROR_CODE security_handler_generate_rsa_key(security_handler_t *security_handler)
To be used to generate the RSA public/private key pairs.
void http_response_destroy(http_response_t **http_response)
To destroy the HTTP Response Handler.
Definition: http_response.c:99
http_request_t * request
It is used to build http request messages.
list_t * high_priority_list
Contains high priority store_data_t data.
Definition: store.h:81
void file_destroy(file_t **file)
Definition: file.c:163
void list_reset(list_t *list)
Reset the current node to head node.
Definition: list.c:329
item_meta_t meta
Meta of file.
Definition: file.h:26
#define DEBUG_LEAVE(...)
Definition: log_util.h:81
static E_MCL_ERROR_CODE _process_registration_response_shared_secret(http_processor_t *http_processor, http_response_t *http_response)
mcl_size_t(* payload_copy_callback_t)(void *destination, void *source, mcl_size_t size, void *user_context)
Definition: http_request.h:93
static E_MCL_ERROR_CODE _exchange_store_data_get_content_info(store_data_t *store_data, string_t **meta_content_type, string_t **meta_content_id, string_t **payload_content_type)
E_MCL_ERROR_CODE security_handler_initialize(security_handler_t **security_handler)
Initializer of security handler.
Type of the data in the store is time series.
Definition: store.h:23
E_MCL_ERROR_CODE json_util_get_string(json_t *json_item, string_t **string_value)
This function gets the string value of a given json object.
Definition: json_util.c:711
Json util module header file.
string_t * content_id
Unique identifier of the group.
Definition: data_types.h:86
Http range header.
time_series_payload_t payload
Payload of time series.
Definition: time_series.h:25
#define DEBUG_ENTRY(...)
Definition: log_util.h:80
E_MCL_ERROR_CODE http_response_get_header(http_response_t *http_response, char *header_name, string_t **header_value)
Get the value of a specified HTTP Header.
Definition: http_response.c:38
Type of the data in the store is stream.
Definition: store.h:27
Http put method.
Definition: http_request.h:67
static E_MCL_ERROR_CODE _concatenate_host_and_endpoint(string_t *host, string_t *endpoint, string_t **uri)
#define STRING_CONSTANT(s)
Definition: definitions.h:135
Common module interface header file.
static E_MCL_ERROR_CODE _exchange_update_store_data_state(store_data_t *store_data, mcl_bool_t send_operation_successful)
#define MCL_NEW(p)
Definition: memory.h:121
If a particular operation is not supported.
Definition: mcl_common.h:148
string_t * mindsphere_hostname
Mindsphere hostname.
Definition: configuration.h:26
E_MCL_ERROR_CODE string_initialize_new(const char *value, mcl_size_t value_length, string_t **string)
Initializes a new string_t object with the given value and length.
Definition: string_type.c:46
Uri for event endpoint.
#define JSON_NAME_KTY
mcl_uint8_t * payload
Payload of http request.
Definition: http_request.h:82
#define MCL_TRUE
Definition: mcl_common.h:54
E_MCL_ERROR_CODE http_request_start_tuple_sub_section(http_request_t *http_request, string_t *content_type, string_t *content_id, string_t **sub_boundary)
To start a sub tuple section inside of the http request body.
Definition: http_request.c:321
char * buffer
Buffer of string handle.
Definition: string_type.h:45
This struct is used for building the complete message of time series event.
Definition: time_series.h:22
configuration_t * configuration
Configuration for mcl initialization.
mcl_bool_t string_util_find(const char *source, const char *target, mcl_size_t *start_index)
Finds the first occurence of target in source and puts it&#39;s first index to start_index.
Definition: string_util.c:156
Type of the data in the store is data source configuration.
Definition: store.h:28
E_MCL_ERROR_CODE previous_result
Previous result of callback.
string_t * exchange_endpoint
Uri for exchange endpoint.
Definition: configuration.h:42
If the response of server is HTTP 403.
Definition: mcl_common.h:186
list_t * low_priority_list
Contains low priority store_data_t data.
Definition: store.h:83
mcl_uint8_t * buffer
Binary payload buffer.
Definition: data_types.h:166
E_MCL_ERROR_CODE json_util_start_array(json_t *root, const char *array_name, json_t **json_array)
This function creates an array in root.
Definition: json_util.c:100
#define JSON_NAME_REGISTRATION_ACCESS_TOKEN
#define HTTP_REQUEST_RESIZE_ENABLED
Definition: http_request.h:54
E_MCL_HTTP_RESULT_CODE result_code
Result code of http response.
Definition: http_response.h:69
string_t * tenant
Tenant name which is used in self issued JWT.
Definition: configuration.h:43
Initial state of a store data. Means this data is not processed before.
Definition: store.h:36
#define JSON_NAME_KEYS
void string_util_strncpy(char *destination, const char *source, mcl_size_t count)
Standard library strncpy wrapper. Also sets the terminating null char at the end if source is not lon...
Definition: string_util.c:48
static E_MCL_ERROR_CODE _exchange_fill_http_request(http_processor_t *http_processor, store_t *store, http_request_t *request)
E_MCL_ERROR_CODE http_request_add_raw_data(http_request_t *http_request, payload_copy_callback_t copy_callback, void *user_context, void *data, mcl_size_t data_size, mcl_size_t *actual_written_size)
To add raw data into an http_request.
Definition: http_request.c:407
#define JSON_NAME_JWKS
static E_MCL_ERROR_CODE _exchange_evaluate_response(store_t *store, E_MCL_ERROR_CODE send_result, http_response_t *response, void **reserved, string_t *correlation_id)
#define MCL_DEBUG(...)
Definition: log_util.h:70
#define MCL_FALSE
MCL bool type.
Definition: mcl_common.h:53
E_MCL_ERROR_CODE _compose_access_token_request_payload(http_processor_t *http_processor, string_t **request_payload)
E_MCL_ERROR_CODE file_initialize(const char *version, const char *file_path, const char *file_name, const char *file_type, const char *routing, file_t **file)
Definition: file.c:22
File module header file.
E_ENDPOINT_TYPE
Enumeration for the Mindsphere endpoints.
E_MCL_ERROR_CODE string_compare_with_cstr(const string_t *string, const char *other)
Compare the contents of string_t with a C string.
Definition: string_type.c:139
E_MCL_ERROR_CODE http_processor_register(http_processor_t *http_processor)
#define MCL_MALLOC(bytes)
Definition: memory.h:120
E_MCL_ERROR_CODE http_client_send(http_client_t *http_client, http_request_t *http_request, http_client_send_callback_info_t *callback_info, http_response_t **http_response)
Send/Receive function.
E_MCL_ERROR_CODE security_generate_random_bytes(unsigned char *buffer, mcl_size_t size)
To be used to generate random bytes.
Http Correlation-ID header name.
mcl_size_t size
Binary payload size.
Definition: data_types.h:167
E_MCL_ERROR_CODE http_request_start_tuple(http_request_t *http_request)
To start a new tuple structure inside the http request body.
Definition: http_request.c:294
Log utility module header file.
HTTP processor module header file.
E_MCL_ERROR_CODE storage_load_shared_secret_registration_information(string_t *path, string_t **client_id, string_t **client_secret, string_t **registration_access_token, string_t **registration_uri)
Definition: storage.c:129
mcl_uint8_t call_count
Call count of stream callback.
static E_MCL_ERROR_CODE _compose_rsa_onboarding_json(security_handler_t *security_handler, string_t **payload)
E_MCL_ERROR_CODE
MCL Error code definitions. Every function returning an error code uses this enum values...
Definition: mcl_common.h:137
Type of the data in the store is custom data.
Definition: store.h:26
E_MCL_ERROR_CODE http_request_end_tuple_sub_section(http_request_t *http_request, string_t *sub_boundary)
To end a sub tuple section previously started with http_request_start_tuple_sub_section().
Definition: http_request.c:382
Content type is application/x-www-form-urlencoded.
Definition: data_types.h:320
E_MCL_ERROR_CODE file_util_fopen(const char *file_name, const char *mode, void **file_descriptor)
Definition: file_util.c:22
mcl_load_registration_information_callback_t load_function
Custom function for loading registration information; if both load_function and save_function are non...
Definition: configuration.h:45
binary_payload_t payload
Payload of custom data.
Definition: custom_data.h:27
mcl_size_t payload_size
Payload size of http response.
Definition: http_response.h:68
mcl_size_t end_byte
File payload end byte.
Definition: data_types.h:156
void json_util_destroy(json_t **root)
This function destroys root.
Definition: json_util.c:863
E_MCL_ERROR_CODE string_util_snprintf(char *string, mcl_size_t length, const char *format,...)
Standard library snprintf wrapper.
Definition: string_util.c:95
Part of the data in store is written to the http request. There is still data left needs to be writte...
Definition: mcl_common.h:219
#define HTTP_REQUEST_RESIZE_DISABLED
Definition: http_request.h:55
Type of the data in the store is file.
Definition: store.h:25
mcl_size_t http_client_get_callback_termination_code()
To get the implementation specific code for returning from callback function in order to terminate th...
Content type is multipart mixed.
Definition: data_types.h:317
Streaming is active. Current data has been partially written to the current http request or about to ...
Definition: store.h:39
E_MCL_ERROR_CODE http_client_initialize(configuration_t *configuration, http_client_t **http_client)
HTTP Client initializer.
#define MCL_FREE(p)
Definition: memory.h:125
E_STORE_DATA_TYPE type
Type of data in the store.
Definition: store.h:66
The store trying to be exchanged has no data inside.
Definition: mcl_common.h:198
static E_MCL_ERROR_CODE _process_registration_response_rsa_3072(http_processor_t *http_processor, http_response_t *http_response)
data_source_configuration_payload_t payload
Payload of data_source_configuration.
void store_data_set_state(store_data_t *store_data, E_STORE_DATA_STATE state)
Definition: store.c:334
mcl_save_shared_secret_callback_t shared_secret
Callback type to save shared secret.
Definition: mcl_common.h:305
static mcl_size_t _get_payload_from_buffer(void *destination, void *source, mcl_size_t size, void *user_context)
Uri for ack event endpoint.
Neither initial access token - initial registration URI pair nor the store path with registration inf...
Definition: mcl_common.h:168
#define ASSERT_STATEMENT_CODE_MESSAGE(condition, statement, return_code,...)
Definition: definitions.h:121
Definition: store.h:77
Json module header file.
E_MCL_HTTP_METHOD
HTTP Method Types.
Definition: http_request.h:62
#define MAX_STREAM_CALLBACK_CALL_COUNT
Type of the data in the store is event list.
Definition: store.h:24
uint16_t mcl_uint16_t
Definition: mcl_common.h:44
struct mcl_list_node_t * next
Next node in the list.
Definition: mcl_list.h:34
string_t * registration_endpoint
Uri for registration endpoint.
Definition: configuration.h:40
mcl_list_node_t * head
Head node of the list.
Definition: mcl_list.h:42
There is no more space left in http message buffer. No data has been written in current call...
Definition: mcl_common.h:216
E_MCL_ERROR_CODE http_request_add_header(http_request_t *http_request, string_t *header_name, string_t *header_value)
To be used to add an HTTP header to the request with it&#39;s value.
Definition: http_request.c:131
string_t * access_token
Access token.
This struct is used for building the complete message of file.
Definition: file.h:24
static E_MCL_ERROR_CODE _exchange_finalize_http_request(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication)
If the response of server is unexpected.
Definition: mcl_common.h:192
void security_handler_destroy(security_handler_t **security_handler)
To destroy the Security Handler.
mcl_save_registration_information_callback_t save_function
Custom function for saving registration information; if both load_function and save_function are non-...
Definition: configuration.h:46
E_MCL_ERROR_CODE storage_save_rsa_registration_information(string_t *path, string_t *client_id, char *public_key, char *private_key, string_t *registration_access_token, string_t *registration_uri)
Definition: storage.c:78
static E_MCL_ERROR_CODE _add_authentication_header_to_request(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication)
char * public_key
Public key.
E_ENDPOINT_URI
Enumeration for URIs for different endpoints.
item_meta_t * meta
Meta of event list.
Definition: event_list.h:27
uint8_t mcl_uint8_t
Definition: mcl_common.h:43
Stream data module header file.
If the response of server is HTTP 206.
Definition: mcl_common.h:183
mcl_load_shared_secret_callback_t shared_secret
Callback type to load shared secret.
Definition: mcl_common.h:296
Http content range header.
#define JSON_NAME_CLIENT_ID
Http post method.
Definition: http_request.h:66
string_t * jwt_get_token(jwt_t *jwt)
Used to generate the JWT Token as json string.
Definition: jwt.c:97
List module header file.
E_MCL_ERROR_CODE security_rsa_get_modulus_and_exponent(char *public_key, char **modulus, char **exponent)
To be used to get the modulus (n) and public exponent (e) parameters of RSA key in Base64 format...
mcl_uint8_t * payload_buffer
Payload of the store.
Definition: store.h:69
E_MCL_ERROR_CODE json_util_get_object_item(json_t *json_parent, const char *child_name, json_t **json_child)
This function gives the value of json_child object, when the child_name in json_parent object is give...
Definition: json_util.c:565
void * descriptor
Descriptor of file.
Definition: file.h:28
string_t * meta
Meta of the store as json string.
Definition: store.h:68
Http authorization header.
void json_util_initialize_json_library()
This function initializes json library.
Definition: json_util.c:28
string_t * access_token_endpoint
Uri for access token endpoint.
Definition: configuration.h:41
void string_util_memcpy(void *destination, const void *source, mcl_size_t count)
Standard library memcpy wrapper.
Definition: string_util.c:131
string_t content_type_values[CONTENT_TYPE_VALUES_END]
Definition: data_types.c:94
string_t * client_secret
Client secret.
http_client_read_callback read_callback
Definition: http_client.h:30
#define ASSERT_STATEMENT_CODE(condition, statement, return_code)
Definition: definitions.h:112
This data has been successfully sent to the server. Can be deleted from the store.
Definition: store.h:40
char * private_key
Private key.
#define ASSERT_CODE_MESSAGE(condition, return_code,...)
Definition: definitions.h:105
string_t http_header_names[HTTP_HEADER_NAMES_END]
E_MCL_ERROR_CODE http_request_finalize(http_request_t *http_request)
Adds closing boundary to the payload and resizes the payload buffer to release unused memory space...
Definition: http_request.c:469
Content type is meta json.
Definition: data_types.h:319
Definitions module header file.
Storage module header file.
store_t * store
Holds references to data to exchange.
static E_MCL_ERROR_CODE _exchange_add_current_data_to_request(store_data_t *current_store_data, http_request_t *request)
Adding final closing boundary and Authentication header is failed.
Definition: mcl_common.h:220
Http content type header.
mcl_size_t payload_offset
Payload offset of http request.
Definition: http_request.h:84
string_t * registration_access_token
Registration access token.
static E_MCL_ERROR_CODE _custom_load_register_info(http_processor_t *http_processor)
If the response of server is HTTP 413.
Definition: mcl_common.h:190
File utility module header file.
#define JSON_NAME_CLIENT_SECRET
Http get method.
Definition: http_request.h:64
E_MCL_SECURITY_PROFILE security_profile
Security levels E_MCL_SECURITY_PROFILE.
Definition: configuration.h:35
Uri for access token endpoint.
void http_client_destroy(http_client_t **http_client)
To destroy the HTTP Client Handler.
file_payload_t payload
Payload of file.
Definition: file.h:27
This struct is used for building the event.
Definition: event_list.h:25
mcl_int64_t size
File payload size.
Definition: data_types.h:154
E_MCL_ERROR_CODE string_initialize_dynamic(const char *value, mcl_size_t value_length, string_t **string)
Initializes a dynamic string_t object with the given value and length.
Definition: string_type.c:68
rsa_t rsa
Rsa handle.
If the response of server is HTTP 400.
Definition: mcl_common.h:184
E_MCL_ERROR_CODE json_from_item_meta(item_meta_t *item_meta, string_t **json_string)
Creates item meta part of all types in json format.
Definition: json.c:37
mcl_size_t length
Length of buffer.
Definition: string_type.h:46
mcl_stream_data_read_callback_t read_callback
Read callback of stream data.
Definition: stream_data.h:30
E_MCL_ERROR_CODE json_util_add_string(json_t *root, const char *object_name, const char *object_value)
This function adds string to root which can be object or array.
Definition: json_util.c:237
If the response of server is HTTP 409.
Definition: mcl_common.h:188
mcl_uint8_t * http_response_get_payload(http_response_t *http_response)
Get the payload section of the HTTP Response.
Definition: http_response.c:83
void jwt_destroy(jwt_t **jwt)
To destroy the JWT Handler.
Definition: jwt.c:128
Time series module header file.
string_t * last_token_time
The time at which the last access token is received.
custom_data_t * base
Type of base is custom data.
Definition: stream_data.h:28
Actual code : 201.
Definition: http_response.h:33
mcl_size_t meta_stream_index
Index of meta stream.
Definition: store.h:45
static E_MCL_ERROR_CODE _exchange_add_current_data_to_request_by_streaming(store_data_t *current_store_data, http_request_t *request)
If the response of server is HTTP 404.
Definition: mcl_common.h:187
void * user_context
User context.
Definition: stream_data.h:29
void file_util_fread(void *data, mcl_size_t size, mcl_size_t count, void *file_descriptor, mcl_size_t *actual_count)
Definition: file_util.c:105
E_MCL_ERROR_CODE http_processor_update_security_information(http_processor_t *http_processor)
list_node_t * list_next(list_t *list)
Get the next node from the list.
Definition: list.c:309
Uri for registration endpoint.
item_meta_t meta
Meta of data source configuration.
E_MCL_ERROR_CODE storage_load_rsa_registration_information(string_t *path, string_t **client_id, char **public_key, char **private_key, string_t **registration_access_token, string_t **registration_uri)
Definition: storage.c:210
This struct is used for building the custom data type.
Definition: custom_data.h:24
E_MCL_ERROR_CODE http_processor_initialize(configuration_t *configuration, http_processor_t **http_processor)
Http Processor Initialize function.
This struct is used for building the complete message of stream data.
Definition: stream_data.h:26
E_STORE_DATA_STATE store_data_get_state(store_data_t *store_data)
Definition: store.c:345
E_MCL_ERROR_CODE string_util_strncmp(const char *string_1, const char *string_2, mcl_size_t count)
Standard library strncmp wrapper.
Definition: string_util.c:74
#define ASSERT_CODE(condition, return_code)
Definition: definitions.h:97
mcl_size_t store_get_data_count(store_t *store)
Definition: store.c:366
Current data has been written to the current http request as a whole.
Definition: store.h:38
E_MCL_ERROR_CODE file_util_fclose(void *file_descriptor)
Definition: file_util.c:52
static E_MCL_ERROR_CODE _exchange_clear_sent_data_from_store(store_t *store)
mcl_size_t payload_stream_index
Index of payload stream.
Definition: store.h:46
void json_util_finish_object(json_t **json_object)
This function destroys json_object data struct. But the object still exists in root json object...
Definition: json_util.c:845
E_MCL_ERROR_CODE http_processor_stream(http_processor_t *http_processor, store_t *store, void **reserved)
Exchange operation logic with streaming.
E_MCL_ERROR_CODE json_util_parse_with_size(const char *json_string, mcl_size_t size, json_t **root)
This function parses the given string to the given json object.
Definition: json_util.c:777
string_t * user_agent
User agent.
Definition: configuration.h:38
If the response of server is HTTP 201.
Definition: mcl_common.h:182
E_MCL_ERROR_CODE http_processor_exchange(http_processor_t *http_processor, store_t *store, void **reserved)
Exchange operation logic.
size_t mcl_size_t
Definition: mcl_common.h:38
Server-Time header name.
E_MCL_ERROR_CODE json_from_time_series_payload(time_series_payload_t *payload, string_t **json_string)
Creates payload part of time series in json format.
Definition: json.c:76
HTTP request module header file.
void http_request_destroy(http_request_t **http_request)
To destroy the HTTP Request Handler.
Definition: http_request.c:497
E_MCL_ERROR_CODE storage_save_shared_secret_registration_information(string_t *path, string_t *client_id, string_t *client_secret, string_t *registration_access_token, string_t *registration_uri)
Definition: storage.c:27
mcl_uint8_t mcl_bool_t
Definition: mcl_common.h:47
mcl_bool_t streamable
Defines if the data in store is streamable or not.
Definition: store.h:79
mcl_size_t max_http_payload_size
Not valid for streamable request. Default value is 16K Bytes. Minimum value is 400 Bytes and maximum ...
Definition: configuration.h:36
Content type is application json.
Definition: data_types.h:316
Success.
Definition: mcl_common.h:140
E_MCL_ERROR_CODE jwt_initialize(security_handler_t *security_handler, E_MCL_SECURITY_PROFILE security_profile, string_t *tenant, jwt_t **jwt)
JWT Initializer.
Definition: jwt.c:70
string_t endpoint_uri[ENDPOINT_URI_END]
Registration information is not loaded.
Definition: mcl_common.h:212
File provided in store path parameter in configuration structure is not accessible.
Definition: mcl_common.h:169
Key rotation endpoint.
Handle struct for security_handler module.
Custom data module header file.
Onboarding endpoint.
static E_MCL_ERROR_CODE _exchange_initialize_http_request_headers(http_processor_t *http_processor, http_request_t *request, mcl_bool_t with_authentication)
#define JSON_NAME_E
security_handler_t * security_handler
Security handler.
#define MCL_ERROR(...)
Definition: log_util.h:97
int payload_state
Payload state.
Definition: store.h:49
mcl_list_node_t * current
Current node of the list.
Definition: mcl_list.h:44
#define CORRELATION_ID_BYTE_LENGTH
void security_initialize(void)
mcl_size_t start_byte
File payload start byte.
Definition: data_types.h:155
#define JSON_NAME_REGISTRATION_CLIENT_URI
E_MCL_ERROR_CODE string_initialize_static(const char *value, mcl_size_t value_length, string_t **string)
Initializes a static string_t object with the given value and length.
Definition: string_type.c:90
Security module header file.Inner security interface. Contains security related functions like hashin...
Actual code : 200.
Definition: http_response.h:32
item_meta_t meta
Meta of time series.
Definition: time_series.h:24
static mcl_size_t _get_payload_from_file(void *destination, void *file_descriptor, mcl_size_t size, void *user_context)
#define MCL_INFO(...)
Definition: log_util.h:87
E_MCL_ERROR_CODE json_util_to_string(json_t *root, char **json_string)
This function gives the string of root in json format.
Definition: json_util.c:737
static E_MCL_ERROR_CODE _exchange_prepare_data(store_data_t *store_data)
E_MCL_ERROR_CODE http_processor_get_access_token(http_processor_t *http_processor)
void * data
Data to be added to the store.
Definition: store.h:65
mcl_size_t count
Node count of the list.
Definition: mcl_list.h:45
int meta_state
Meta state.
Definition: store.h:48
The streaming is active and shouldn&#39;t be interrupted.
Definition: mcl_common.h:199
string_t * registration_client_uri
Registration client uri.
Json object.
Definition: json_util.h:35
http_processor_t * http_processor
Http processer handle.
Random module header file.
HTTP Response Handle.
Definition: http_response.h:64
E_MCL_ERROR_CODE json_from_data_source_configuration_payload(data_source_configuration_payload_t *payload, string_t **json_string)
Creates payload part of data source configuration in json format.
Definition: json.c:104
Store which is not streamable has an item that does not fit in a single http request.
Definition: mcl_common.h:205
string_t * initial_access_token
Initial access token. Not used by the library if a registration access token is present in store_path...
Definition: configuration.h:39
#define JSON_NAME_N
JWT Module handler.
Definition: jwt.h:25
Event list module header file.
Memory allocation fail.
Definition: mcl_common.h:143
string_t * tuple_subboundary
Subboundary of tuple.
Definition: store.h:47
#define MCL_NULL
Definition: definitions.h:24
Prepared. Means its meta and payload strings has been prepared.
Definition: store.h:37
Http content disposition header.
string_t * store_path
Path of the file the library uses to save registration artifacts such as registration access token...
Definition: configuration.h:44
void json_util_add_item_to_array(json_t *root, json_t *object)
This function adds object to root array.
Definition: json_util.c:540
mcl_size_t http_request_get_available_space_for_raw_data(http_request_t *http_request)
To be used to get the available space left in the request buffer in order to add a raw data...
Definition: http_request.c:438
Security information of the mcl_communication is already up to date.
Definition: mcl_common.h:200
string_t * client_id
Client id.
Uri for download endpoint.
E_MCL_ERROR_CODE http_request_initialize(E_MCL_HTTP_METHOD method, string_t *uri, mcl_size_t header_size, mcl_size_t payload_size, mcl_bool_t resize_enabled, string_t *user_agent, mcl_size_t max_http_payload_size, http_request_t **http_request)
HTTP Request Initializer.
Definition: http_request.c:79
static E_MCL_ERROR_CODE _add_key_to_keys_array(json_t *root, json_t **json_object)
E_MCL_ERROR_CODE _save_registration_information(http_processor_t *http_processor)
Exchange endpoint.
void * data
Data of the node.
Definition: mcl_list.h:32
If the response of server is HTTP 429.
Definition: mcl_common.h:191
mcl_size_t payload_size
Payload size of http request.
Definition: http_request.h:83
Internal server error.
Definition: mcl_common.h:181
E_MCL_ERROR_CODE json_from_event_payload(list_t *event_list_payload, string_t **json_string)
Creates payload part of event set in json format.
Definition: json.c:129
E_MCL_ERROR_CODE http_request_add_tuple(http_request_t *http_request, string_t *meta, string_t *meta_content_type, payload_copy_callback_t payload_copy_callback, void *user_context, void *payload, mcl_size_t payload_size, string_t *payload_content_type)
To be used to add a tuple to the HTTP Request.
Definition: http_request.c:214
E_MCL_ERROR_CODE json_util_start_object(json_t *root, const char *object_name, json_t **json_object)
This function creates an object in root.
Definition: json_util.c:198
E_MCL_ERROR_CODE store_data_remove(list_t *store_list, list_node_t *store_data_node)
Definition: store.c:355
JWT module header file.
static E_MCL_ERROR_CODE _evaluate_response_codes(http_response_t *response)
E_MCL_ERROR_CODE json_util_initialize(E_JSON_TYPE json_type, json_t **root)
This function initializes the given root json.
Definition: json_util.c:53
E_MCL_ERROR_CODE string_concatenate(string_t *string_1, string_t *string_2, string_t **result)
Concatenates a C string (i.e. a char array)
Definition: string_type.c:416
Indicates that a provided buffer does not have enough size for the operation.
Definition: mcl_common.h:213
Uri for exchange endpoint.
mcl_size_t string_util_strlen(const char *buffer)
Standard library strlen wrapper.
Definition: string_util.c:24
E_STORE_DATA_STATE
Definition: store.h:34
If the response of server is HTTP 401.
Definition: mcl_common.h:185
static E_MCL_ERROR_CODE _generate_correlation_id_string(string_t **correlation_id)
Time utility module header file.
void http_processor_destroy(http_processor_t **http_processor)
To destroy the HTTP Processor Handler.
static E_MCL_ERROR_CODE _check_file_path(const char *file_name)
mcl_size_t payload_size
Size of the payload in the store.
Definition: store.h:70
This struct is used for json handling.
Definition: json_util.h:27
#define MAX_RANGE_HEADER_LENGTH
mcl_save_rsa_callback_t rsa
Callback type to save RSA key.
Definition: mcl_common.h:306
#define MCL_NULL_CHAR
Definition: definitions.h:26
If the response of server is HTTP 412.
Definition: mcl_common.h:189
End of uri endpoint.
Data types module header file.
mcl_uint8_t * payload
Payload of http response.
Definition: http_response.h:67
#define MCL_ERROR_RETURN(return_value,...)
Definition: definitions.h:69