Microsoft Azure IoTHub client libraries
Dependents: sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp f767zi_mqtt ... more
This library implements the Microsoft Azure IoTHub client library. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: iothub_client_ll_uploadtoblob.c
- Revision:
- 46:6a69294b6119
- Parent:
- 45:54c11b1b1407
- Child:
- 47:aaa262b5f898
--- a/iothub_client_ll_uploadtoblob.c Fri Jul 01 10:42:36 2016 -0700 +++ b/iothub_client_ll_uploadtoblob.c Mon Jul 18 16:45:01 2016 -0700 @@ -30,10 +30,17 @@ #define AUTHORIZATION_SCHEME_VALUES \ DEVICE_KEY, \ + X509, \ SAS_TOKEN DEFINE_ENUM(AUTHORIZATION_SCHEME, AUTHORIZATION_SCHEME_VALUES); +typedef struct UPLOADTOBLOB_X509_CREDENTIALS_TAG +{ + const char* x509certificate; + const char* x509privatekey; +}UPLOADTOBLOB_X509_CREDENTIALS; + typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA_TAG { STRING_HANDLE deviceId; /*needed for file upload*/ @@ -42,6 +49,7 @@ union { STRING_HANDLE deviceKey; /*used when authorizationScheme is DEVICE_KEY*/ STRING_HANDLE sas; /*used when authorizationScheme is SAS_TOKEN*/ + UPLOADTOBLOB_X509_CREDENTIALS x509credentials; /*assumed to be used when both deviceKey and deviceSasToken are NULL*/ } credentials; /*needed for file upload*/ }IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA; @@ -79,7 +87,7 @@ memcpy((char*)handleData->hostname, config->iotHubName, iotHubNameLength); ((char*)handleData->hostname)[iotHubNameLength] = '.'; memcpy((char*)handleData->hostname + iotHubNameLength + 1, config->iotHubSuffix, iotHubSuffixLength + 1); /*+1 will copy the \0 too*/ - if (config->deviceSasToken != NULL) + if ((config->deviceSasToken != NULL) && (config->deviceKey == NULL)) { handleData->authorizationScheme = SAS_TOKEN; handleData->credentials.sas = STRING_construct(config->deviceSasToken); @@ -96,7 +104,7 @@ /*return as is*/ } } - else + else if ((config->deviceSasToken == NULL) && (config->deviceKey != NULL)) { handleData->authorizationScheme = DEVICE_KEY; handleData->credentials.deviceKey = STRING_construct(config->deviceKey); @@ -113,6 +121,13 @@ /*return as is*/ } } + else if ((config->deviceSasToken == NULL) && (config->deviceKey == NULL)) + { + handleData->authorizationScheme = X509; + handleData->credentials.x509credentials.x509certificate = NULL; + handleData->credentials.x509credentials.x509privatekey = NULL; + /*return as is*/ + } } } } @@ -160,11 +175,12 @@ else { /*Codes_SRS_IOTHUBCLIENT_LL_02_072: [ IoTHubClient_LL_UploadToBlob shall add the following name:value to request HTTP headers: ] "Content-Type": "application/json" "Accept": "application/json" "User-Agent": "iothubclient/" IOTHUB_SDK_VERSION*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_107: [ - "Authorization" header shall not be build. ]*/ if (!( (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", "application/json") == HTTP_HEADERS_OK) && (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) && (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) && - (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Authorization", "") == HTTP_HEADERS_OK) + (handleData->authorizationScheme==X509 || (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Authorization", "") == HTTP_HEADERS_OK)) )) { /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ @@ -174,12 +190,49 @@ else { int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/ + /* set the result to error by default */ + result = __LINE__; switch (handleData->authorizationScheme) { default: { /*wasIoTHubRequestSuccess takes care of the return value*/ LogError("Internal Error: unexpected value in handleData->authorizationScheme = %d", handleData->authorizationScheme); + result = __LINE__; + break; + } + case(X509): + { + unsigned int statusCode; + /*Codes_SRS_IOTHUBCLIENT_LL_02_108: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/ + if (HTTPAPIEX_ExecuteRequest( + iotHubHttpApiExHandle, /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/ + HTTPAPI_REQUEST_GET, /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_GET*/ + STRING_c_str(relativePath), /*const char* relativePath - the HTTP relative path*/ + requestHttpHeaders, /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/ + NULL, /*BUFFER_HANDLE requestContent - NULL*/ + &statusCode, /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/ + NULL, /*HTTP_HEADERS_HANDLE responseHttpHeadersHandl - NULL*/ + responseContent /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/ + ) != HTTPAPIEX_OK) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + result = __LINE__; + LogError("unable to HTTPAPIEX_ExecuteRequest"); + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + if (statusCode >= 300) + { + result = __LINE__; + LogError("HTTP code was %u", statusCode); + } + else + { + wasIoTHubRequestSuccess = 1; + } + } break; } case (SAS_TOKEN): @@ -217,7 +270,6 @@ if (statusCode >= 300) { result = __LINE__; - wasIoTHubRequestSuccess = 0; LogError("HTTP code was %u", statusCode); } else @@ -505,6 +557,37 @@ result = __LINE__; break; } + case (X509): + { + unsigned int notificationStatusCode; + if (HTTPAPIEX_ExecuteRequest( + iotHubHttpApiExHandle, + HTTPAPI_REQUEST_POST, + STRING_c_str(relativePathNotification), + requestHttpHeaders, + messageBody, + ¬ificationStatusCode, + NULL, + NULL) != HTTPAPIEX_OK) + { + LogError("unable to do HTTPAPIEX_ExecuteRequest"); + result = __LINE__; + } + else + { + if (notificationStatusCode >= 300) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/ + LogError("server didn't like the notification request"); + result = __LINE__; + } + else + { + result = 0; + } + } + break; + } case (DEVICE_KEY): { STRING_HANDLE empty = STRING_new(); @@ -632,115 +715,133 @@ } else { - STRING_HANDLE correlationId = STRING_new(); - if (correlationId == NULL) + if ( + (handleData->authorizationScheme == X509) && + + /*transmit the x509certificate and x509privatekey*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_106: [ - x509certificate and x509privatekey saved options shall be passed on the HTTPAPIEX_SetOption ]*/ + (!( + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, "x509certificate", handleData->credentials.x509credentials.x509certificate) == HTTPAPIEX_OK) && + (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, "x509privatekey", handleData->credentials.x509credentials.x509privatekey) == HTTPAPIEX_OK) + )) + ) { - LogError("unable to STRING_new"); + LogError("unable to HTTPAPIEX_SetOption for x509"); result = IOTHUB_CLIENT_ERROR; } else { - STRING_HANDLE sasUri = STRING_new(); - if (sasUri == NULL) + + STRING_HANDLE correlationId = STRING_new(); + if (correlationId == NULL) { LogError("unable to STRING_new"); result = IOTHUB_CLIENT_ERROR; } else { - /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/ - HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/ - if (requestHttpHeaders == NULL) + STRING_HANDLE sasUri = STRING_new(); + if (sasUri == NULL) { - LogError("unable to HTTPHeaders_Alloc"); + LogError("unable to STRING_new"); result = IOTHUB_CLIENT_ERROR; } else { - /*do step 1*/ - if (IoTHubClient_LL_UploadToBlob_step1and2(handleData, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0) + /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/ + HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/ + if (requestHttpHeaders == NULL) { - LogError("error in IoTHubClient_LL_UploadToBlob_step1"); + LogError("unable to HTTPHeaders_Alloc"); result = IOTHUB_CLIENT_ERROR; } else { - /*do step 2.*/ - - unsigned int httpResponse; - BUFFER_HANDLE responseToIoTHub = BUFFER_new(); - if (responseToIoTHub == NULL) + /*do step 1*/ + if (IoTHubClient_LL_UploadToBlob_step1and2(handleData, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0) { + LogError("error in IoTHubClient_LL_UploadToBlob_step1"); result = IOTHUB_CLIENT_ERROR; - LogError("unable to BUFFER_new"); } else { - int step2success; - /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/ - step2success = (Blob_UploadFromSasUri(STRING_c_str(sasUri), source, size, &httpResponse, responseToIoTHub) == BLOB_OK); - if (!step2success) - { - /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("unable to Blob_UploadFromSasUri"); + /*do step 2.*/ - /*do step 3*/ /*try*/ - /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/ - if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0) - { - if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0) - { - LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); - } - } + unsigned int httpResponse; + BUFFER_HANDLE responseToIoTHub = BUFFER_new(); + if (responseToIoTHub == NULL) + { result = IOTHUB_CLIENT_ERROR; + LogError("unable to BUFFER_new"); } else { - /*must make a json*/ - - int requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); + int step2success; + /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/ + step2success = (Blob_UploadFromSasUri(STRING_c_str(sasUri), source, size, &httpResponse, responseToIoTHub) == BLOB_OK); + if (!step2success) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to Blob_UploadFromSasUri"); - char* requiredString = malloc(requiredStringLength + 1); - if (requiredString == 0) - { - LogError("unable to malloc"); + /*do step 3*/ /*try*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/ + if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0) + { + if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0) + { + LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); + } + } result = IOTHUB_CLIENT_ERROR; } else { - /*do again snprintf*/ - (void)snprintf(requiredString, requiredStringLength + 1, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); - BUFFER_HANDLE toBeTransmitted = BUFFER_create(requiredString, requiredStringLength); - if (toBeTransmitted == NULL) + /*must make a json*/ + + int requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); + + char* requiredString = malloc(requiredStringLength + 1); + if (requiredString == 0) { - LogError("unable to BUFFER_create"); + LogError("unable to malloc"); result = IOTHUB_CLIENT_ERROR; } else { - if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0) + /*do again snprintf*/ + (void)snprintf(requiredString, requiredStringLength + 1, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); + BUFFER_HANDLE toBeTransmitted = BUFFER_create((const unsigned char*)requiredString, requiredStringLength); + if (toBeTransmitted == NULL) { - LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); + LogError("unable to BUFFER_create"); result = IOTHUB_CLIENT_ERROR; } else { - result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR; + if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0) + { + LogError("IoTHubClient_LL_UploadToBlob_step3 failed"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR; + } + BUFFER_delete(toBeTransmitted); } - BUFFER_delete(toBeTransmitted); + free(requiredString); } - free(requiredString); } + BUFFER_delete(responseToIoTHub); } - BUFFER_delete(responseToIoTHub); } + HTTPHeaders_Free(requestHttpHeaders); } - HTTPHeaders_Free(requestHttpHeaders); + STRING_delete(sasUri); } - STRING_delete(sasUri); + STRING_delete(correlationId); } - STRING_delete(correlationId); } HTTPAPIEX_Destroy(iotHubHttpApiExHandle); } @@ -769,6 +870,18 @@ STRING_delete(handleData->credentials.deviceKey); break; } + case(X509): + { + if (handleData->credentials.x509credentials.x509certificate != NULL) + { + free((void*)handleData->credentials.x509credentials.x509certificate); + } + if (handleData->credentials.x509credentials.x509privatekey != NULL) + { + free((void*)handleData->credentials.x509credentials.x509privatekey); + } + break; + } default: { LogError("INTERNAL ERROR"); @@ -780,4 +893,94 @@ free(handleData); } } + +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_SetOption(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* optionName, const void* value) +{ + IOTHUB_CLIENT_RESULT result; + /*Codes_SRS_IOTHUBCLIENT_LL_02_110: [ If parameter handle is NULL then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + if (handle == NULL) + { + LogError("invalid argument detected: IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle=%p, const char* optionName=%s, const void* value=%p", handle, optionName, value); + result = IOTHUB_CLIENT_ERROR; + } + else + { + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; + + /*Codes_SRS_IOTHUBCLIENT_LL_02_100: [ x509certificate - then value then is a null terminated string that contains the x509 certificate. ]*/ + if (strcmp(optionName, "x509certificate") == 0) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ + if (handleData->authorizationScheme != X509) + { + LogError("trying to set a x509 certificate while the authentication scheme is not x509"); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/ + /*try to make a copy of the certificate*/ + char* temp; + if (mallocAndStrcpy_s(&temp, value) != 0) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to mallocAndStrcpy_s"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/ + if (handleData->credentials.x509credentials.x509certificate != NULL) /*free any previous values, if any*/ + { + free((void*)handleData->credentials.x509credentials.x509certificate); + } + handleData->credentials.x509credentials.x509certificate = temp; + result = IOTHUB_CLIENT_OK; + } + } + } + /*Codes_SRS_IOTHUBCLIENT_LL_02_101: [ x509privatekey - then value is a null terminated string that contains the x509 privatekey. ]*/ + else if (strcmp(optionName, "x509privatekey") == 0) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ + if (handleData->authorizationScheme != X509) + { + LogError("trying to set a x509 privatekey while the authentication scheme is not x509"); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/ + /*try to make a copy of the privatekey*/ + char* temp; + if (mallocAndStrcpy_s(&temp, value) != 0) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("unable to mallocAndStrcpy_s"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/ + if (handleData->credentials.x509credentials.x509privatekey != NULL) /*free any previous values, if any*/ + { + free((void*)handleData->credentials.x509credentials.x509privatekey); + } + handleData->credentials.x509credentials.x509privatekey = temp; + result = IOTHUB_CLIENT_OK; + } + } + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_102: [ If an unknown option is presented then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ + result = IOTHUB_CLIENT_INVALID_ARG; + } + } + return result; +} + + #endif /*DONT_USE_UPLOADTOBLOB*/ + +