Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XinZhangMS 0:f7f1f0d76dd6 1 // Copyright (c) Microsoft. All rights reserved.
XinZhangMS 0:f7f1f0d76dd6 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
XinZhangMS 0:f7f1f0d76dd6 3
XinZhangMS 0:f7f1f0d76dd6 4 #include <stdlib.h>
XinZhangMS 0:f7f1f0d76dd6 5 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 6
XinZhangMS 0:f7f1f0d76dd6 7 #include <time.h>
XinZhangMS 0:f7f1f0d76dd6 8 #include "iothub_client_options.h"
XinZhangMS 0:f7f1f0d76dd6 9 #include "iothub_client_version.h"
XinZhangMS 0:f7f1f0d76dd6 10 #include "internal/iothub_client_private.h"
XinZhangMS 0:f7f1f0d76dd6 11 #include "iothub_transport_ll.h"
XinZhangMS 0:f7f1f0d76dd6 12 #include "iothubtransporthttp.h"
XinZhangMS 0:f7f1f0d76dd6 13 #include "internal/iothubtransport.h"
XinZhangMS 0:f7f1f0d76dd6 14
XinZhangMS 0:f7f1f0d76dd6 15 #include "azure_c_shared_utility/optimize_size.h"
XinZhangMS 0:f7f1f0d76dd6 16 #include "azure_c_shared_utility/httpapiexsas.h"
XinZhangMS 0:f7f1f0d76dd6 17 #include "azure_c_shared_utility/urlencode.h"
XinZhangMS 0:f7f1f0d76dd6 18 #include "azure_c_shared_utility/xlogging.h"
XinZhangMS 0:f7f1f0d76dd6 19 #include "azure_c_shared_utility/httpapiex.h"
XinZhangMS 0:f7f1f0d76dd6 20 #include "azure_c_shared_utility/httpapiexsas.h"
XinZhangMS 0:f7f1f0d76dd6 21 #include "azure_c_shared_utility/strings.h"
XinZhangMS 0:f7f1f0d76dd6 22 #include "azure_c_shared_utility/base64.h"
XinZhangMS 0:f7f1f0d76dd6 23 #include "azure_c_shared_utility/doublylinkedlist.h"
XinZhangMS 0:f7f1f0d76dd6 24 #include "azure_c_shared_utility/vector.h"
XinZhangMS 0:f7f1f0d76dd6 25 #include "azure_c_shared_utility/httpheaders.h"
XinZhangMS 0:f7f1f0d76dd6 26 #include "azure_c_shared_utility/agenttime.h"
XinZhangMS 0:f7f1f0d76dd6 27
XinZhangMS 0:f7f1f0d76dd6 28 #define IOTHUB_APP_PREFIX "iothub-app-"
XinZhangMS 0:f7f1f0d76dd6 29 static const char* IOTHUB_MESSAGE_ID = "iothub-messageid";
XinZhangMS 0:f7f1f0d76dd6 30 static const char* IOTHUB_CORRELATION_ID = "iothub-correlationid";
XinZhangMS 0:f7f1f0d76dd6 31 static const char* IOTHUB_CONTENT_TYPE_D2C = "iothub-contenttype";
XinZhangMS 0:f7f1f0d76dd6 32 static const char* IOTHUB_CONTENT_ENCODING_D2C = "iothub-contentencoding";
XinZhangMS 0:f7f1f0d76dd6 33 static const char* IOTHUB_CONTENT_TYPE_C2D = "ContentType";
XinZhangMS 0:f7f1f0d76dd6 34 static const char* IOTHUB_CONTENT_ENCODING_C2D = "ContentEncoding";
XinZhangMS 0:f7f1f0d76dd6 35
XinZhangMS 0:f7f1f0d76dd6 36 #define CONTENT_TYPE "Content-Type"
XinZhangMS 0:f7f1f0d76dd6 37 #define APPLICATION_OCTET_STREAM "application/octet-stream"
XinZhangMS 0:f7f1f0d76dd6 38 #define APPLICATION_VND_MICROSOFT_IOTHUB_JSON "application/vnd.microsoft.iothub.json"
XinZhangMS 0:f7f1f0d76dd6 39
XinZhangMS 0:f7f1f0d76dd6 40 /*DEFAULT_GETMINIMUMPOLLINGTIME is the minimum time in seconds allowed between 2 consecutive GET issues to the service (GET=fetch messages)*/
XinZhangMS 0:f7f1f0d76dd6 41 /*the default is 25 minutes*/
XinZhangMS 0:f7f1f0d76dd6 42 #define DEFAULT_GETMINIMUMPOLLINGTIME ((unsigned int)25*60)
XinZhangMS 0:f7f1f0d76dd6 43
XinZhangMS 0:f7f1f0d76dd6 44 #define MAXIMUM_MESSAGE_SIZE (255*1024-1)
XinZhangMS 0:f7f1f0d76dd6 45 #define MAXIMUM_PAYLOAD_OVERHEAD 384
XinZhangMS 0:f7f1f0d76dd6 46 #define MAXIMUM_PROPERTY_OVERHEAD 16
XinZhangMS 0:f7f1f0d76dd6 47
XinZhangMS 0:f7f1f0d76dd6 48 /*forward declaration*/
XinZhangMS 0:f7f1f0d76dd6 49 static int appendMapToJSON(STRING_HANDLE existing, const char* const* keys, const char* const* values, size_t count);
XinZhangMS 0:f7f1f0d76dd6 50
XinZhangMS 0:f7f1f0d76dd6 51 typedef struct HTTPTRANSPORT_HANDLE_DATA_TAG
XinZhangMS 0:f7f1f0d76dd6 52 {
XinZhangMS 0:f7f1f0d76dd6 53 STRING_HANDLE hostName;
XinZhangMS 0:f7f1f0d76dd6 54 HTTPAPIEX_HANDLE httpApiExHandle;
XinZhangMS 0:f7f1f0d76dd6 55 bool doBatchedTransfers;
XinZhangMS 0:f7f1f0d76dd6 56 unsigned int getMinimumPollingTime;
XinZhangMS 0:f7f1f0d76dd6 57 VECTOR_HANDLE perDeviceList;
XinZhangMS 0:f7f1f0d76dd6 58 }HTTPTRANSPORT_HANDLE_DATA;
XinZhangMS 0:f7f1f0d76dd6 59
XinZhangMS 0:f7f1f0d76dd6 60 typedef struct HTTPTRANSPORT_PERDEVICE_DATA_TAG
XinZhangMS 0:f7f1f0d76dd6 61 {
XinZhangMS 0:f7f1f0d76dd6 62 HTTPTRANSPORT_HANDLE_DATA* transportHandle;
XinZhangMS 0:f7f1f0d76dd6 63
XinZhangMS 0:f7f1f0d76dd6 64 STRING_HANDLE deviceId;
XinZhangMS 0:f7f1f0d76dd6 65 STRING_HANDLE deviceKey;
XinZhangMS 0:f7f1f0d76dd6 66 STRING_HANDLE deviceSasToken;
XinZhangMS 0:f7f1f0d76dd6 67 STRING_HANDLE eventHTTPrelativePath;
XinZhangMS 0:f7f1f0d76dd6 68 STRING_HANDLE messageHTTPrelativePath;
XinZhangMS 0:f7f1f0d76dd6 69 HTTP_HEADERS_HANDLE eventHTTPrequestHeaders;
XinZhangMS 0:f7f1f0d76dd6 70 HTTP_HEADERS_HANDLE messageHTTPrequestHeaders;
XinZhangMS 0:f7f1f0d76dd6 71 STRING_HANDLE abandonHTTPrelativePathBegin;
XinZhangMS 0:f7f1f0d76dd6 72 HTTPAPIEX_SAS_HANDLE sasObject;
XinZhangMS 0:f7f1f0d76dd6 73 bool DoWork_PullMessage;
XinZhangMS 0:f7f1f0d76dd6 74 time_t lastPollTime;
XinZhangMS 0:f7f1f0d76dd6 75 bool isFirstPoll;
XinZhangMS 0:f7f1f0d76dd6 76
XinZhangMS 0:f7f1f0d76dd6 77 IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle;
XinZhangMS 0:f7f1f0d76dd6 78 PDLIST_ENTRY waitingToSend;
XinZhangMS 0:f7f1f0d76dd6 79 DLIST_ENTRY eventConfirmations; /*holds items for event confirmations*/
XinZhangMS 0:f7f1f0d76dd6 80 } HTTPTRANSPORT_PERDEVICE_DATA;
XinZhangMS 0:f7f1f0d76dd6 81
XinZhangMS 0:f7f1f0d76dd6 82 typedef struct MESSAGE_DISPOSITION_CONTEXT_TAG
XinZhangMS 0:f7f1f0d76dd6 83 {
XinZhangMS 0:f7f1f0d76dd6 84 HTTPTRANSPORT_HANDLE_DATA* handleData;
XinZhangMS 0:f7f1f0d76dd6 85 HTTPTRANSPORT_PERDEVICE_DATA* deviceData;
XinZhangMS 0:f7f1f0d76dd6 86 char* etagValue;
XinZhangMS 0:f7f1f0d76dd6 87 } MESSAGE_DISPOSITION_CONTEXT;
XinZhangMS 0:f7f1f0d76dd6 88
XinZhangMS 0:f7f1f0d76dd6 89 DEFINE_ENUM_STRINGS(IOTHUBMESSAGE_DISPOSITION_RESULT, IOTHUBMESSAGE_DISPOSITION_RESULT_VALUES);
XinZhangMS 0:f7f1f0d76dd6 90
XinZhangMS 0:f7f1f0d76dd6 91 static void destroy_eventHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 92 {
XinZhangMS 0:f7f1f0d76dd6 93 STRING_delete(handleData->eventHTTPrelativePath);
XinZhangMS 0:f7f1f0d76dd6 94 handleData->eventHTTPrelativePath = NULL;
XinZhangMS 0:f7f1f0d76dd6 95 }
XinZhangMS 0:f7f1f0d76dd6 96
XinZhangMS 0:f7f1f0d76dd6 97 static bool create_eventHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
XinZhangMS 0:f7f1f0d76dd6 98 {
XinZhangMS 0:f7f1f0d76dd6 99 /*Codes_SRS_TRANSPORTMULTITHTTP_17_017: [ IoTHubTransportHttp_Register shall create an immutable string (further called "event HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(deviceId) + "/messages/events" + APIVERSION. ]*/
XinZhangMS 0:f7f1f0d76dd6 100 bool result;
XinZhangMS 0:f7f1f0d76dd6 101 STRING_HANDLE urlEncodedDeviceId;
XinZhangMS 0:f7f1f0d76dd6 102 handleData->eventHTTPrelativePath = STRING_construct("/devices/");
XinZhangMS 0:f7f1f0d76dd6 103 if (handleData->eventHTTPrelativePath == NULL)
XinZhangMS 0:f7f1f0d76dd6 104 {
XinZhangMS 0:f7f1f0d76dd6 105 LogError("STRING_construct failed.");
XinZhangMS 0:f7f1f0d76dd6 106 result = false;
XinZhangMS 0:f7f1f0d76dd6 107 }
XinZhangMS 0:f7f1f0d76dd6 108 else
XinZhangMS 0:f7f1f0d76dd6 109 {
XinZhangMS 0:f7f1f0d76dd6 110 if (!(
XinZhangMS 0:f7f1f0d76dd6 111 ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 112 (STRING_concat_with_STRING(handleData->eventHTTPrelativePath, urlEncodedDeviceId) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 113 (STRING_concat(handleData->eventHTTPrelativePath, EVENT_ENDPOINT API_VERSION) == 0)
XinZhangMS 0:f7f1f0d76dd6 114 ))
XinZhangMS 0:f7f1f0d76dd6 115 {
XinZhangMS 0:f7f1f0d76dd6 116 /*Codes_SRS_TRANSPORTMULTITHTTP_17_018: [ If creating the string fail for any reason then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 117 destroy_eventHTTPrelativePath(handleData);
XinZhangMS 0:f7f1f0d76dd6 118 LogError("Creating HTTP event relative path failed.");
XinZhangMS 0:f7f1f0d76dd6 119 result = false;
XinZhangMS 0:f7f1f0d76dd6 120 }
XinZhangMS 0:f7f1f0d76dd6 121 else
XinZhangMS 0:f7f1f0d76dd6 122 {
XinZhangMS 0:f7f1f0d76dd6 123 result = true;
XinZhangMS 0:f7f1f0d76dd6 124 }
XinZhangMS 0:f7f1f0d76dd6 125 STRING_delete(urlEncodedDeviceId);
XinZhangMS 0:f7f1f0d76dd6 126 }
XinZhangMS 0:f7f1f0d76dd6 127 return result;
XinZhangMS 0:f7f1f0d76dd6 128 }
XinZhangMS 0:f7f1f0d76dd6 129
XinZhangMS 0:f7f1f0d76dd6 130 static void destroy_messageHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 131 {
XinZhangMS 0:f7f1f0d76dd6 132 STRING_delete(handleData->messageHTTPrelativePath);
XinZhangMS 0:f7f1f0d76dd6 133 handleData->messageHTTPrelativePath = NULL;
XinZhangMS 0:f7f1f0d76dd6 134 }
XinZhangMS 0:f7f1f0d76dd6 135
XinZhangMS 0:f7f1f0d76dd6 136 static bool create_messageHTTPrelativePath(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
XinZhangMS 0:f7f1f0d76dd6 137 {
XinZhangMS 0:f7f1f0d76dd6 138 bool result;
XinZhangMS 0:f7f1f0d76dd6 139 handleData->messageHTTPrelativePath = STRING_construct("/devices/");
XinZhangMS 0:f7f1f0d76dd6 140 if (handleData->messageHTTPrelativePath == NULL)
XinZhangMS 0:f7f1f0d76dd6 141 {
XinZhangMS 0:f7f1f0d76dd6 142 LogError("STRING_construct failed.");
XinZhangMS 0:f7f1f0d76dd6 143 result = false;
XinZhangMS 0:f7f1f0d76dd6 144 }
XinZhangMS 0:f7f1f0d76dd6 145 else
XinZhangMS 0:f7f1f0d76dd6 146 {
XinZhangMS 0:f7f1f0d76dd6 147 STRING_HANDLE urlEncodedDeviceId;
XinZhangMS 0:f7f1f0d76dd6 148 /*Codes_SRS_TRANSPORTMULTITHTTP_17_019: [ IoTHubTransportHttp_Register shall create an immutable string (further called "message HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(deviceId) + "/messages/devicebound" + APIVERSION. ]*/
XinZhangMS 0:f7f1f0d76dd6 149 if (!(
XinZhangMS 0:f7f1f0d76dd6 150 ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 151 (STRING_concat_with_STRING(handleData->messageHTTPrelativePath, urlEncodedDeviceId) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 152 (STRING_concat(handleData->messageHTTPrelativePath, MESSAGE_ENDPOINT_HTTP API_VERSION) == 0)
XinZhangMS 0:f7f1f0d76dd6 153 ))
XinZhangMS 0:f7f1f0d76dd6 154 {
XinZhangMS 0:f7f1f0d76dd6 155 /*Codes_SRS_TRANSPORTMULTITHTTP_17_020: [ If creating the message HTTP relative path fails, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 156 LogError("Creating HTTP message relative path failed.");
XinZhangMS 0:f7f1f0d76dd6 157 result = false;
XinZhangMS 0:f7f1f0d76dd6 158 destroy_messageHTTPrelativePath(handleData);
XinZhangMS 0:f7f1f0d76dd6 159 }
XinZhangMS 0:f7f1f0d76dd6 160 else
XinZhangMS 0:f7f1f0d76dd6 161 {
XinZhangMS 0:f7f1f0d76dd6 162 result = true;
XinZhangMS 0:f7f1f0d76dd6 163 }
XinZhangMS 0:f7f1f0d76dd6 164 STRING_delete(urlEncodedDeviceId);
XinZhangMS 0:f7f1f0d76dd6 165 }
XinZhangMS 0:f7f1f0d76dd6 166
XinZhangMS 0:f7f1f0d76dd6 167 return result;
XinZhangMS 0:f7f1f0d76dd6 168 }
XinZhangMS 0:f7f1f0d76dd6 169
XinZhangMS 0:f7f1f0d76dd6 170 static void destroy_eventHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 171 {
XinZhangMS 0:f7f1f0d76dd6 172 HTTPHeaders_Free(handleData->eventHTTPrequestHeaders);
XinZhangMS 0:f7f1f0d76dd6 173 handleData->eventHTTPrequestHeaders = NULL;
XinZhangMS 0:f7f1f0d76dd6 174 }
XinZhangMS 0:f7f1f0d76dd6 175
XinZhangMS 0:f7f1f0d76dd6 176 static HTTP_HEADERS_RESULT addUserAgentHeaderInfo(IOTHUB_CLIENT_CORE_LL_HANDLE hClient, HTTP_HEADERS_HANDLE eventHTTPrequestHeaders)
XinZhangMS 0:f7f1f0d76dd6 177 {
XinZhangMS 0:f7f1f0d76dd6 178 void* product_info;
XinZhangMS 0:f7f1f0d76dd6 179 HTTP_HEADERS_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 180 if ((IoTHubClientCore_LL_GetOption(hClient, OPTION_PRODUCT_INFO, &product_info) == IOTHUB_CLIENT_ERROR) || (product_info == NULL))
XinZhangMS 0:f7f1f0d76dd6 181 {
XinZhangMS 0:f7f1f0d76dd6 182 result = HTTPHeaders_AddHeaderNameValuePair(eventHTTPrequestHeaders, "User-Agent", CLIENT_DEVICE_TYPE_PREFIX CLIENT_DEVICE_BACKSLASH IOTHUB_SDK_VERSION);
XinZhangMS 0:f7f1f0d76dd6 183 }
XinZhangMS 0:f7f1f0d76dd6 184 else
XinZhangMS 0:f7f1f0d76dd6 185 {
XinZhangMS 0:f7f1f0d76dd6 186 result = HTTPHeaders_AddHeaderNameValuePair(eventHTTPrequestHeaders, "User-Agent", STRING_c_str((STRING_HANDLE)product_info));
XinZhangMS 0:f7f1f0d76dd6 187 }
XinZhangMS 0:f7f1f0d76dd6 188 return result;
XinZhangMS 0:f7f1f0d76dd6 189 }
XinZhangMS 0:f7f1f0d76dd6 190
XinZhangMS 0:f7f1f0d76dd6 191 static bool create_eventHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId, bool is_x509_used)
XinZhangMS 0:f7f1f0d76dd6 192 {
XinZhangMS 0:f7f1f0d76dd6 193 /*Codes_SRS_TRANSPORTMULTITHTTP_17_021: [ IoTHubTransportHttp_Register shall create a set of HTTP headers (further called "event HTTP request headers") consisting of the following fixed field names and values: "iothub-to":"/devices/" + URL_ENCODED(deviceId) + "/messages/events"; "Authorization":""
XinZhangMS 0:f7f1f0d76dd6 194 "Accept":"application/json"
XinZhangMS 0:f7f1f0d76dd6 195 "Connection":"Keep-Alive" ]*/
XinZhangMS 0:f7f1f0d76dd6 196 bool result;
XinZhangMS 0:f7f1f0d76dd6 197 handleData->eventHTTPrequestHeaders = HTTPHeaders_Alloc();
XinZhangMS 0:f7f1f0d76dd6 198 if (handleData->eventHTTPrequestHeaders == NULL)
XinZhangMS 0:f7f1f0d76dd6 199 {
XinZhangMS 0:f7f1f0d76dd6 200 LogError("HTTPHeaders_Alloc failed.");
XinZhangMS 0:f7f1f0d76dd6 201 result = false;
XinZhangMS 0:f7f1f0d76dd6 202 }
XinZhangMS 0:f7f1f0d76dd6 203 else
XinZhangMS 0:f7f1f0d76dd6 204 {
XinZhangMS 0:f7f1f0d76dd6 205 STRING_HANDLE temp = STRING_construct("/devices/");
XinZhangMS 0:f7f1f0d76dd6 206 if (temp == NULL)
XinZhangMS 0:f7f1f0d76dd6 207 {
XinZhangMS 0:f7f1f0d76dd6 208 LogError("STRING_construct failed.");
XinZhangMS 0:f7f1f0d76dd6 209 result = false;
XinZhangMS 0:f7f1f0d76dd6 210 destroy_eventHTTPrequestHeaders(handleData);
XinZhangMS 0:f7f1f0d76dd6 211 }
XinZhangMS 0:f7f1f0d76dd6 212 else
XinZhangMS 0:f7f1f0d76dd6 213 {
XinZhangMS 0:f7f1f0d76dd6 214 STRING_HANDLE urlEncodedDeviceId;
XinZhangMS 0:f7f1f0d76dd6 215 if (!(
XinZhangMS 0:f7f1f0d76dd6 216 ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 217 (STRING_concat_with_STRING(temp, urlEncodedDeviceId) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 218 (STRING_concat(temp, EVENT_ENDPOINT) == 0)
XinZhangMS 0:f7f1f0d76dd6 219 ))
XinZhangMS 0:f7f1f0d76dd6 220 {
XinZhangMS 0:f7f1f0d76dd6 221 LogError("deviceId construction failed.");
XinZhangMS 0:f7f1f0d76dd6 222 result = false;
XinZhangMS 0:f7f1f0d76dd6 223 destroy_eventHTTPrequestHeaders(handleData);
XinZhangMS 0:f7f1f0d76dd6 224 }
XinZhangMS 0:f7f1f0d76dd6 225 else
XinZhangMS 0:f7f1f0d76dd6 226 {
XinZhangMS 0:f7f1f0d76dd6 227 if (!(
XinZhangMS 0:f7f1f0d76dd6 228 (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "iothub-to", STRING_c_str(temp)) == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 229 (is_x509_used || (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "Authorization", " ") == HTTP_HEADERS_OK)) &&
XinZhangMS 0:f7f1f0d76dd6 230 (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 231 (HTTPHeaders_AddHeaderNameValuePair(handleData->eventHTTPrequestHeaders, "Connection", "Keep-Alive") == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 232 (addUserAgentHeaderInfo(handleData->iotHubClientHandle, handleData->eventHTTPrequestHeaders) == HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 233 ))
XinZhangMS 0:f7f1f0d76dd6 234 {
XinZhangMS 0:f7f1f0d76dd6 235 /*Codes_SRS_TRANSPORTMULTITHTTP_17_022: [ If creating the event HTTP request headers fails, then IoTHubTransportHttp_Register shall fail and return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 236 LogError("adding header properties failed.");
XinZhangMS 0:f7f1f0d76dd6 237 result = false;
XinZhangMS 0:f7f1f0d76dd6 238 destroy_eventHTTPrequestHeaders(handleData);
XinZhangMS 0:f7f1f0d76dd6 239 }
XinZhangMS 0:f7f1f0d76dd6 240 else
XinZhangMS 0:f7f1f0d76dd6 241 {
XinZhangMS 0:f7f1f0d76dd6 242 result = true;
XinZhangMS 0:f7f1f0d76dd6 243 }
XinZhangMS 0:f7f1f0d76dd6 244 }
XinZhangMS 0:f7f1f0d76dd6 245 STRING_delete(urlEncodedDeviceId);
XinZhangMS 0:f7f1f0d76dd6 246 STRING_delete(temp);
XinZhangMS 0:f7f1f0d76dd6 247 }
XinZhangMS 0:f7f1f0d76dd6 248 }
XinZhangMS 0:f7f1f0d76dd6 249 return result;
XinZhangMS 0:f7f1f0d76dd6 250 }
XinZhangMS 0:f7f1f0d76dd6 251
XinZhangMS 0:f7f1f0d76dd6 252 static void destroy_messageHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 253 {
XinZhangMS 0:f7f1f0d76dd6 254 HTTPHeaders_Free(handleData->messageHTTPrequestHeaders);
XinZhangMS 0:f7f1f0d76dd6 255 handleData->messageHTTPrequestHeaders = NULL;
XinZhangMS 0:f7f1f0d76dd6 256 }
XinZhangMS 0:f7f1f0d76dd6 257
XinZhangMS 0:f7f1f0d76dd6 258 static bool create_messageHTTPrequestHeaders(HTTPTRANSPORT_PERDEVICE_DATA* handleData, bool is_x509_used)
XinZhangMS 0:f7f1f0d76dd6 259 {
XinZhangMS 0:f7f1f0d76dd6 260 /*Codes_SRS_TRANSPORTMULTITHTTP_17_132: [ IoTHubTransportHttp_Register shall create a set of HTTP headers (further called "message HTTP request headers") consisting of the following fixed field names and values:
XinZhangMS 0:f7f1f0d76dd6 261 "Authorization": "" ]*/
XinZhangMS 0:f7f1f0d76dd6 262 bool result;
XinZhangMS 0:f7f1f0d76dd6 263 handleData->messageHTTPrequestHeaders = HTTPHeaders_Alloc();
XinZhangMS 0:f7f1f0d76dd6 264 if (handleData->messageHTTPrequestHeaders == NULL)
XinZhangMS 0:f7f1f0d76dd6 265 {
XinZhangMS 0:f7f1f0d76dd6 266 LogError("HTTPHeaders_Alloc failed.");
XinZhangMS 0:f7f1f0d76dd6 267 result = false;
XinZhangMS 0:f7f1f0d76dd6 268 }
XinZhangMS 0:f7f1f0d76dd6 269 else
XinZhangMS 0:f7f1f0d76dd6 270 {
XinZhangMS 0:f7f1f0d76dd6 271 if (!(
XinZhangMS 0:f7f1f0d76dd6 272 (addUserAgentHeaderInfo(handleData->iotHubClientHandle, handleData->messageHTTPrequestHeaders) == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 273 (is_x509_used || (HTTPHeaders_AddHeaderNameValuePair(handleData->messageHTTPrequestHeaders, "Authorization", " ") == HTTP_HEADERS_OK))
XinZhangMS 0:f7f1f0d76dd6 274 ))
XinZhangMS 0:f7f1f0d76dd6 275 {
XinZhangMS 0:f7f1f0d76dd6 276 /*Codes_SRS_TRANSPORTMULTITHTTP_17_023: [ If creating message HTTP request headers then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 277 destroy_messageHTTPrequestHeaders(handleData);
XinZhangMS 0:f7f1f0d76dd6 278 LogError("adding header properties failed.");
XinZhangMS 0:f7f1f0d76dd6 279 result = false;
XinZhangMS 0:f7f1f0d76dd6 280 }
XinZhangMS 0:f7f1f0d76dd6 281 else
XinZhangMS 0:f7f1f0d76dd6 282 {
XinZhangMS 0:f7f1f0d76dd6 283 result = true;
XinZhangMS 0:f7f1f0d76dd6 284 }
XinZhangMS 0:f7f1f0d76dd6 285 }
XinZhangMS 0:f7f1f0d76dd6 286 return result;
XinZhangMS 0:f7f1f0d76dd6 287 }
XinZhangMS 0:f7f1f0d76dd6 288
XinZhangMS 0:f7f1f0d76dd6 289 static void destroy_abandonHTTPrelativePathBegin(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 290 {
XinZhangMS 0:f7f1f0d76dd6 291 STRING_delete(handleData->abandonHTTPrelativePathBegin);
XinZhangMS 0:f7f1f0d76dd6 292 handleData->abandonHTTPrelativePathBegin = NULL;
XinZhangMS 0:f7f1f0d76dd6 293 }
XinZhangMS 0:f7f1f0d76dd6 294
XinZhangMS 0:f7f1f0d76dd6 295 static bool create_abandonHTTPrelativePathBegin(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
XinZhangMS 0:f7f1f0d76dd6 296 {
XinZhangMS 0:f7f1f0d76dd6 297 /*Codes_SRS_TRANSPORTMULTITHTTP_17_024: [ IoTHubTransportHttp_Register shall create a STRING containing: "/devices/" + URL_ENCODED(device id) +"/messages/deviceBound/" called abandonHTTPrelativePathBegin. ]*/
XinZhangMS 0:f7f1f0d76dd6 298 bool result;
XinZhangMS 0:f7f1f0d76dd6 299 handleData->abandonHTTPrelativePathBegin = STRING_construct("/devices/");
XinZhangMS 0:f7f1f0d76dd6 300 if (handleData->abandonHTTPrelativePathBegin == NULL)
XinZhangMS 0:f7f1f0d76dd6 301 {
XinZhangMS 0:f7f1f0d76dd6 302 result = false;
XinZhangMS 0:f7f1f0d76dd6 303 }
XinZhangMS 0:f7f1f0d76dd6 304 else
XinZhangMS 0:f7f1f0d76dd6 305 {
XinZhangMS 0:f7f1f0d76dd6 306 STRING_HANDLE urlEncodedDeviceId;
XinZhangMS 0:f7f1f0d76dd6 307 if (!(
XinZhangMS 0:f7f1f0d76dd6 308 ((urlEncodedDeviceId = URL_EncodeString(deviceId)) != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 309 (STRING_concat_with_STRING(handleData->abandonHTTPrelativePathBegin, urlEncodedDeviceId) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 310 (STRING_concat(handleData->abandonHTTPrelativePathBegin, MESSAGE_ENDPOINT_HTTP_ETAG) == 0)
XinZhangMS 0:f7f1f0d76dd6 311 ))
XinZhangMS 0:f7f1f0d76dd6 312 {
XinZhangMS 0:f7f1f0d76dd6 313 /*Codes_SRS_TRANSPORTMULTITHTTP_17_025: [ If creating the abandonHTTPrelativePathBegin fails then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 314 LogError("unable to create abandon path string.");
XinZhangMS 0:f7f1f0d76dd6 315 STRING_delete(handleData->abandonHTTPrelativePathBegin);
XinZhangMS 0:f7f1f0d76dd6 316 result = false;
XinZhangMS 0:f7f1f0d76dd6 317 }
XinZhangMS 0:f7f1f0d76dd6 318 else
XinZhangMS 0:f7f1f0d76dd6 319 {
XinZhangMS 0:f7f1f0d76dd6 320 result = true;
XinZhangMS 0:f7f1f0d76dd6 321 }
XinZhangMS 0:f7f1f0d76dd6 322 STRING_delete(urlEncodedDeviceId);
XinZhangMS 0:f7f1f0d76dd6 323 }
XinZhangMS 0:f7f1f0d76dd6 324 return result;
XinZhangMS 0:f7f1f0d76dd6 325 }
XinZhangMS 0:f7f1f0d76dd6 326
XinZhangMS 0:f7f1f0d76dd6 327 static void destroy_SASObject(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 328 {
XinZhangMS 0:f7f1f0d76dd6 329 HTTPAPIEX_SAS_Destroy(handleData->sasObject);
XinZhangMS 0:f7f1f0d76dd6 330 handleData->sasObject = NULL;
XinZhangMS 0:f7f1f0d76dd6 331 }
XinZhangMS 0:f7f1f0d76dd6 332
XinZhangMS 0:f7f1f0d76dd6 333 static bool create_deviceSASObject(HTTPTRANSPORT_PERDEVICE_DATA* handleData, STRING_HANDLE hostName, const char * deviceId, const char * deviceKey)
XinZhangMS 0:f7f1f0d76dd6 334 {
XinZhangMS 0:f7f1f0d76dd6 335 STRING_HANDLE keyName;
XinZhangMS 0:f7f1f0d76dd6 336 bool result;
XinZhangMS 0:f7f1f0d76dd6 337 /*Codes_SRS_TRANSPORTMULTITHTTP_17_026: [IoTHubTransportHttp_Create shall invoke URL_EncodeString with an argument of device id.]*/
XinZhangMS 0:f7f1f0d76dd6 338 keyName = URL_EncodeString(deviceId);
XinZhangMS 0:f7f1f0d76dd6 339 if (keyName == NULL)
XinZhangMS 0:f7f1f0d76dd6 340 {
XinZhangMS 0:f7f1f0d76dd6 341 /*Codes_SRS_TRANSPORTMULTITHTTP_17_027: [If the encode fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 342 LogError("URL_EncodeString keyname failed");
XinZhangMS 0:f7f1f0d76dd6 343 result = false;
XinZhangMS 0:f7f1f0d76dd6 344 }
XinZhangMS 0:f7f1f0d76dd6 345 else
XinZhangMS 0:f7f1f0d76dd6 346 {
XinZhangMS 0:f7f1f0d76dd6 347 STRING_HANDLE uriResource;
XinZhangMS 0:f7f1f0d76dd6 348 /*Codes_SRS_TRANSPORTMULTITHTTP_17_028: [IoTHubTransportHttp_Create shall invoke STRING_clone using the previously created hostname.]*/
XinZhangMS 0:f7f1f0d76dd6 349 uriResource = STRING_clone(hostName);
XinZhangMS 0:f7f1f0d76dd6 350 /*Codes_SRS_TRANSPORTMULTITHTTP_17_029: [If the clone fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 351 if (uriResource != NULL)
XinZhangMS 0:f7f1f0d76dd6 352 {
XinZhangMS 0:f7f1f0d76dd6 353 /*Codes_SRS_TRANSPORTMULTITHTTP_17_030: [IoTHubTransportHttp_Create shall invoke STRING_concat with arguments uriResource and the string "/devices/".]*/
XinZhangMS 0:f7f1f0d76dd6 354 /*Codes_SRS_TRANSPORTMULTITHTTP_17_141: [If the concat fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 355 /*Codes_SRS_TRANSPORTMULTITHTTP_17_031: [IoTHubTransportHttp_Create shall invoke STRING_concat_with_STRING with arguments uriResource and keyName.]*/
XinZhangMS 0:f7f1f0d76dd6 356 /*Codes_SRS_TRANSPORTMULTITHTTP_17_032: [If the STRING_concat_with_STRING fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 357 if ((STRING_concat(uriResource, "/devices/") == 0) &&
XinZhangMS 0:f7f1f0d76dd6 358 (STRING_concat_with_STRING(uriResource, keyName) == 0))
XinZhangMS 0:f7f1f0d76dd6 359 {
XinZhangMS 0:f7f1f0d76dd6 360 /*Codes_SRS_TRANSPORTMULTITHTTP_17_033: [IoTHubTransportHttp_Create shall invoke STRING_construct with an argument of config->upperConfig->deviceKey.]*/
XinZhangMS 0:f7f1f0d76dd6 361 /*Codes_SRS_TRANSPORTMULTITHTTP_17_034: [If the STRING_construct fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 362 STRING_HANDLE key = STRING_construct(deviceKey);
XinZhangMS 0:f7f1f0d76dd6 363 if (key != NULL)
XinZhangMS 0:f7f1f0d76dd6 364 {
XinZhangMS 0:f7f1f0d76dd6 365 /*Codes_SRS_TRANSPORTMULTITHTTP_17_035: [The keyName is shortened to zero length, if that fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 366 if (STRING_empty(keyName) != 0)
XinZhangMS 0:f7f1f0d76dd6 367 {
XinZhangMS 0:f7f1f0d76dd6 368 LogError("Unable to form the device key name for the SAS");
XinZhangMS 0:f7f1f0d76dd6 369 result = false;
XinZhangMS 0:f7f1f0d76dd6 370 }
XinZhangMS 0:f7f1f0d76dd6 371 else
XinZhangMS 0:f7f1f0d76dd6 372 {
XinZhangMS 0:f7f1f0d76dd6 373 /*Codes_SRS_TRANSPORTMULTITHTTP_17_036: [IoTHubTransportHttp_Create shall invoke HTTPAPIEX_SAS_Create with arguments key, uriResource, and zero length keyName.]*/
XinZhangMS 0:f7f1f0d76dd6 374 /*Codes_SRS_TRANSPORTMULTITHTTP_17_037: [If the HTTPAPIEX_SAS_Create fails then IoTHubTransportHttp_Create shall fail and return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 375 handleData->sasObject = HTTPAPIEX_SAS_Create(key, uriResource, keyName);
XinZhangMS 0:f7f1f0d76dd6 376 result = (handleData->sasObject != NULL) ? (true) : (false);
XinZhangMS 0:f7f1f0d76dd6 377 }
XinZhangMS 0:f7f1f0d76dd6 378 STRING_delete(key);
XinZhangMS 0:f7f1f0d76dd6 379 }
XinZhangMS 0:f7f1f0d76dd6 380 else
XinZhangMS 0:f7f1f0d76dd6 381 {
XinZhangMS 0:f7f1f0d76dd6 382 LogError("STRING_construct Key failed");
XinZhangMS 0:f7f1f0d76dd6 383 result = false;
XinZhangMS 0:f7f1f0d76dd6 384 }
XinZhangMS 0:f7f1f0d76dd6 385 }
XinZhangMS 0:f7f1f0d76dd6 386 else
XinZhangMS 0:f7f1f0d76dd6 387 {
XinZhangMS 0:f7f1f0d76dd6 388 LogError("STRING_concat uri resource failed");
XinZhangMS 0:f7f1f0d76dd6 389 result = false;
XinZhangMS 0:f7f1f0d76dd6 390 }
XinZhangMS 0:f7f1f0d76dd6 391 STRING_delete(uriResource);
XinZhangMS 0:f7f1f0d76dd6 392 }
XinZhangMS 0:f7f1f0d76dd6 393 else
XinZhangMS 0:f7f1f0d76dd6 394 {
XinZhangMS 0:f7f1f0d76dd6 395 LogError("STRING_staticclone uri resource failed");
XinZhangMS 0:f7f1f0d76dd6 396 result = false;
XinZhangMS 0:f7f1f0d76dd6 397 }
XinZhangMS 0:f7f1f0d76dd6 398 STRING_delete(keyName);
XinZhangMS 0:f7f1f0d76dd6 399 }
XinZhangMS 0:f7f1f0d76dd6 400 return result;
XinZhangMS 0:f7f1f0d76dd6 401 }
XinZhangMS 0:f7f1f0d76dd6 402
XinZhangMS 0:f7f1f0d76dd6 403 static void destroy_deviceId(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 404 {
XinZhangMS 0:f7f1f0d76dd6 405 STRING_delete(handleData->deviceId);
XinZhangMS 0:f7f1f0d76dd6 406 handleData->deviceId = NULL;
XinZhangMS 0:f7f1f0d76dd6 407 }
XinZhangMS 0:f7f1f0d76dd6 408
XinZhangMS 0:f7f1f0d76dd6 409 static bool create_deviceId(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceId)
XinZhangMS 0:f7f1f0d76dd6 410 {
XinZhangMS 0:f7f1f0d76dd6 411 /*Codes_SRS_TRANSPORTMULTITHTTP_17_133: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceId") from config->deviceConfig->deviceId. ]*/
XinZhangMS 0:f7f1f0d76dd6 412 bool result;
XinZhangMS 0:f7f1f0d76dd6 413 handleData->deviceId = STRING_construct(deviceId);
XinZhangMS 0:f7f1f0d76dd6 414 if (handleData->deviceId == NULL)
XinZhangMS 0:f7f1f0d76dd6 415 {
XinZhangMS 0:f7f1f0d76dd6 416 /*Codes_SRS_TRANSPORTMULTITHTTP_17_134: [ If deviceId is not created, then IoTHubTransportHttp_Register shall fail and return NULL. */
XinZhangMS 0:f7f1f0d76dd6 417 LogError("STRING_construct deviceId failed");
XinZhangMS 0:f7f1f0d76dd6 418 result = false;
XinZhangMS 0:f7f1f0d76dd6 419 }
XinZhangMS 0:f7f1f0d76dd6 420 else
XinZhangMS 0:f7f1f0d76dd6 421 {
XinZhangMS 0:f7f1f0d76dd6 422 result = true;
XinZhangMS 0:f7f1f0d76dd6 423 }
XinZhangMS 0:f7f1f0d76dd6 424 return result;
XinZhangMS 0:f7f1f0d76dd6 425 }
XinZhangMS 0:f7f1f0d76dd6 426
XinZhangMS 0:f7f1f0d76dd6 427 static void destroy_deviceKey(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 428 {
XinZhangMS 0:f7f1f0d76dd6 429 STRING_delete(handleData->deviceKey);
XinZhangMS 0:f7f1f0d76dd6 430 handleData->deviceKey = NULL;
XinZhangMS 0:f7f1f0d76dd6 431 }
XinZhangMS 0:f7f1f0d76dd6 432
XinZhangMS 0:f7f1f0d76dd6 433 static void destroy_deviceSas(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 434 {
XinZhangMS 0:f7f1f0d76dd6 435 STRING_delete(handleData->deviceSasToken);
XinZhangMS 0:f7f1f0d76dd6 436 handleData->deviceSasToken = NULL;
XinZhangMS 0:f7f1f0d76dd6 437 }
XinZhangMS 0:f7f1f0d76dd6 438
XinZhangMS 0:f7f1f0d76dd6 439 static bool create_deviceKey(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceKey)
XinZhangMS 0:f7f1f0d76dd6 440 {
XinZhangMS 0:f7f1f0d76dd6 441 /*Codes_SRS_TRANSPORTMULTITHTTP_17_135: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceKey") from deviceKey. ]*/
XinZhangMS 0:f7f1f0d76dd6 442 bool result;
XinZhangMS 0:f7f1f0d76dd6 443 handleData->deviceKey = STRING_construct(deviceKey);
XinZhangMS 0:f7f1f0d76dd6 444 if (handleData->deviceKey == NULL)
XinZhangMS 0:f7f1f0d76dd6 445 {
XinZhangMS 0:f7f1f0d76dd6 446 /*Codes_SRS_TRANSPORTMULTITHTTP_17_136: [ If deviceKey is not created, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 447 LogError("STRING_construct deviceKey failed");
XinZhangMS 0:f7f1f0d76dd6 448 result = false;
XinZhangMS 0:f7f1f0d76dd6 449 }
XinZhangMS 0:f7f1f0d76dd6 450 else
XinZhangMS 0:f7f1f0d76dd6 451 {
XinZhangMS 0:f7f1f0d76dd6 452 result = true;
XinZhangMS 0:f7f1f0d76dd6 453 }
XinZhangMS 0:f7f1f0d76dd6 454 return result;
XinZhangMS 0:f7f1f0d76dd6 455 }
XinZhangMS 0:f7f1f0d76dd6 456
XinZhangMS 0:f7f1f0d76dd6 457 static void destroy_deviceSasToken(HTTPTRANSPORT_PERDEVICE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 458 {
XinZhangMS 0:f7f1f0d76dd6 459 STRING_delete(handleData->deviceSasToken);
XinZhangMS 0:f7f1f0d76dd6 460 handleData->deviceSasToken = NULL;
XinZhangMS 0:f7f1f0d76dd6 461 }
XinZhangMS 0:f7f1f0d76dd6 462
XinZhangMS 0:f7f1f0d76dd6 463 static bool create_deviceSasToken(HTTPTRANSPORT_PERDEVICE_DATA* handleData, const char * deviceSasToken)
XinZhangMS 0:f7f1f0d76dd6 464 {
XinZhangMS 0:f7f1f0d76dd6 465 /*Codes_SRS_TRANSPORTMULTITHTTP_03_135: [ IoTHubTransportHttp_Register shall create an immutable string (further called "deviceSasToken") from deviceSasToken. ]*/
XinZhangMS 0:f7f1f0d76dd6 466 bool result;
XinZhangMS 0:f7f1f0d76dd6 467 handleData->deviceSasToken = STRING_construct(deviceSasToken);
XinZhangMS 0:f7f1f0d76dd6 468 if (handleData->deviceSasToken == NULL)
XinZhangMS 0:f7f1f0d76dd6 469 {
XinZhangMS 0:f7f1f0d76dd6 470 /*Codes_SRS_TRANSPORTMULTITHTTP_03_136: [ If deviceSasToken is not created, then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 471 LogError("STRING_construct deviceSasToken failed");
XinZhangMS 0:f7f1f0d76dd6 472 result = false;
XinZhangMS 0:f7f1f0d76dd6 473 }
XinZhangMS 0:f7f1f0d76dd6 474 else
XinZhangMS 0:f7f1f0d76dd6 475 {
XinZhangMS 0:f7f1f0d76dd6 476 result = true;
XinZhangMS 0:f7f1f0d76dd6 477 }
XinZhangMS 0:f7f1f0d76dd6 478 return result;
XinZhangMS 0:f7f1f0d76dd6 479 }
XinZhangMS 0:f7f1f0d76dd6 480
XinZhangMS 0:f7f1f0d76dd6 481 /*
XinZhangMS 0:f7f1f0d76dd6 482 * List queries Find by handle and find by device name
XinZhangMS 0:f7f1f0d76dd6 483 */
XinZhangMS 0:f7f1f0d76dd6 484
XinZhangMS 0:f7f1f0d76dd6 485 /*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 486 static bool findDeviceHandle(const void* element, const void* value)
XinZhangMS 0:f7f1f0d76dd6 487 {
XinZhangMS 0:f7f1f0d76dd6 488 bool result;
XinZhangMS 0:f7f1f0d76dd6 489 /* data stored at element is device handle */
XinZhangMS 0:f7f1f0d76dd6 490 const IOTHUB_DEVICE_HANDLE * guess = (const IOTHUB_DEVICE_HANDLE *)element;
XinZhangMS 0:f7f1f0d76dd6 491 IOTHUB_DEVICE_HANDLE match = (IOTHUB_DEVICE_HANDLE)value;
XinZhangMS 0:f7f1f0d76dd6 492 result = (*guess == match) ? true : false;
XinZhangMS 0:f7f1f0d76dd6 493 return result;
XinZhangMS 0:f7f1f0d76dd6 494 }
XinZhangMS 0:f7f1f0d76dd6 495
XinZhangMS 0:f7f1f0d76dd6 496 static bool findDeviceById(const void* element, const void* value)
XinZhangMS 0:f7f1f0d76dd6 497 {
XinZhangMS 0:f7f1f0d76dd6 498 bool result;
XinZhangMS 0:f7f1f0d76dd6 499 const char* deviceId = (const char *)value;
XinZhangMS 0:f7f1f0d76dd6 500 const HTTPTRANSPORT_PERDEVICE_DATA * perDeviceElement = *(const HTTPTRANSPORT_PERDEVICE_DATA **)element;
XinZhangMS 0:f7f1f0d76dd6 501
XinZhangMS 0:f7f1f0d76dd6 502 result = (strcmp(STRING_c_str(perDeviceElement->deviceId), deviceId) == 0);
XinZhangMS 0:f7f1f0d76dd6 503
XinZhangMS 0:f7f1f0d76dd6 504 return result;
XinZhangMS 0:f7f1f0d76dd6 505 }
XinZhangMS 0:f7f1f0d76dd6 506
XinZhangMS 0:f7f1f0d76dd6 507 static IOTHUB_DEVICE_HANDLE IoTHubTransportHttp_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, PDLIST_ENTRY waitingToSend)
XinZhangMS 0:f7f1f0d76dd6 508 {
XinZhangMS 0:f7f1f0d76dd6 509 HTTPTRANSPORT_PERDEVICE_DATA* result;
XinZhangMS 0:f7f1f0d76dd6 510 if (handle == NULL || device == NULL)
XinZhangMS 0:f7f1f0d76dd6 511 {
XinZhangMS 0:f7f1f0d76dd6 512 /*Codes_SRS_TRANSPORTMULTITHTTP_17_142: [ If handle is NULL or device is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 513 LogError("Transport handle is NULL");
XinZhangMS 0:f7f1f0d76dd6 514 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 515 }
XinZhangMS 0:f7f1f0d76dd6 516 else if (device->deviceId == NULL || ((device->deviceKey != NULL) && (device->deviceSasToken != NULL)) || waitingToSend == NULL || iotHubClientHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 517 {
XinZhangMS 0:f7f1f0d76dd6 518 /*Codes_SRS_TRANSPORTMULTITHTTP_17_015: [ If IOTHUB_DEVICE_CONFIG fields deviceKey and deviceSasToken are NULL, then IoTHubTransportHttp_Register shall assume a x509 authentication. ]*/
XinZhangMS 0:f7f1f0d76dd6 519 /*Codes_SRS_TRANSPORTMULTITHTTP_17_014: [ If IOTHUB_DEVICE_CONFIG field deviceId is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 520 /*Codes_SRS_TRANSPORTMULTITHTTP_17_016: [ If parameter waitingToSend is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 521 /*Codes_SRS_TRANSPORTMULTITHTTP_17_143: [ If parameter iotHubClientHandle is NULL, then IoTHubTransportHttp_Register shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 522 LogError("invalid parameters detected TRANSPORT_LL_HANDLE handle=%p, const IOTHUB_DEVICE_CONFIG* device=%p, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, PDLIST_ENTRY waitingToSend=%p",
XinZhangMS 0:f7f1f0d76dd6 523 handle, device, iotHubClientHandle, waitingToSend);
XinZhangMS 0:f7f1f0d76dd6 524 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 525 }
XinZhangMS 0:f7f1f0d76dd6 526 else
XinZhangMS 0:f7f1f0d76dd6 527 {
XinZhangMS 0:f7f1f0d76dd6 528 HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 529 /*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 530 void* listItem = VECTOR_find_if(handleData->perDeviceList, findDeviceById, device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 531 if (listItem != NULL)
XinZhangMS 0:f7f1f0d76dd6 532 {
XinZhangMS 0:f7f1f0d76dd6 533 /*Codes_SRS_TRANSPORTMULTITHTTP_17_137: [ IoTHubTransportHttp_Register shall search the devices list for any device matching name deviceId. If deviceId is found it shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 534 LogError("Transport already has device registered by id: [%s]", device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 535 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 536 }
XinZhangMS 0:f7f1f0d76dd6 537 else
XinZhangMS 0:f7f1f0d76dd6 538 {
XinZhangMS 0:f7f1f0d76dd6 539 bool was_create_deviceKey_ok = false;
XinZhangMS 0:f7f1f0d76dd6 540 bool was_create_deviceSasToken_ok = false;
XinZhangMS 0:f7f1f0d76dd6 541 bool was_sasObject_ok = false;
XinZhangMS 0:f7f1f0d76dd6 542 bool was_x509_ok = false; /*there's nothing "created" in the case of x509, it is a flag indicating that x509 is used*/
XinZhangMS 0:f7f1f0d76dd6 543
XinZhangMS 0:f7f1f0d76dd6 544 /*Codes_SRS_TRANSPORTMULTITHTTP_17_038: [ Otherwise, IoTHubTransportHttp_Register shall allocate the IOTHUB_DEVICE_HANDLE structure. ]*/
XinZhangMS 0:f7f1f0d76dd6 545 bool was_resultCreated_ok = ((result = (HTTPTRANSPORT_PERDEVICE_DATA *)malloc(sizeof(HTTPTRANSPORT_PERDEVICE_DATA))) != NULL);
XinZhangMS 0:f7f1f0d76dd6 546 bool was_create_deviceId_ok = was_resultCreated_ok && create_deviceId(result, device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 547
XinZhangMS 0:f7f1f0d76dd6 548 if (was_create_deviceId_ok)
XinZhangMS 0:f7f1f0d76dd6 549 {
XinZhangMS 0:f7f1f0d76dd6 550 if (device->deviceSasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 551 {
XinZhangMS 0:f7f1f0d76dd6 552 /*device->deviceKey is certainly NULL (because of the validation condition (else if (device->deviceId == NULL || ((device->deviceKey != NULL) && (device->deviceSasToken != NULL)) || waitingToSend == NULL || iotHubClientHandle == NULL))that does not accept that both satoken AND devicekey are non-NULL*/
XinZhangMS 0:f7f1f0d76dd6 553 was_create_deviceSasToken_ok = create_deviceSasToken(result, device->deviceSasToken);
XinZhangMS 0:f7f1f0d76dd6 554 result->deviceKey = NULL;
XinZhangMS 0:f7f1f0d76dd6 555 result->sasObject = NULL;
XinZhangMS 0:f7f1f0d76dd6 556 }
XinZhangMS 0:f7f1f0d76dd6 557 else /*when deviceSasToken == NULL*/
XinZhangMS 0:f7f1f0d76dd6 558 {
XinZhangMS 0:f7f1f0d76dd6 559 if (device->deviceKey != NULL)
XinZhangMS 0:f7f1f0d76dd6 560 {
XinZhangMS 0:f7f1f0d76dd6 561 was_create_deviceKey_ok = create_deviceKey(result, device->deviceKey);
XinZhangMS 0:f7f1f0d76dd6 562 result->deviceSasToken = NULL;
XinZhangMS 0:f7f1f0d76dd6 563 }
XinZhangMS 0:f7f1f0d76dd6 564 else
XinZhangMS 0:f7f1f0d76dd6 565 {
XinZhangMS 0:f7f1f0d76dd6 566 /*when both of them are NULL*/
XinZhangMS 0:f7f1f0d76dd6 567 was_x509_ok = true;
XinZhangMS 0:f7f1f0d76dd6 568 result->deviceKey = NULL;
XinZhangMS 0:f7f1f0d76dd6 569 result->deviceSasToken = NULL;
XinZhangMS 0:f7f1f0d76dd6 570 }
XinZhangMS 0:f7f1f0d76dd6 571 }
XinZhangMS 0:f7f1f0d76dd6 572 }
XinZhangMS 0:f7f1f0d76dd6 573
XinZhangMS 0:f7f1f0d76dd6 574 bool was_eventHTTPrelativePath_ok = (was_create_deviceKey_ok || was_create_deviceSasToken_ok || was_x509_ok) && create_eventHTTPrelativePath(result, device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 575 bool was_messageHTTPrelativePath_ok = was_eventHTTPrelativePath_ok && create_messageHTTPrelativePath(result, device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 576 bool was_eventHTTPrequestHeaders_ok;
XinZhangMS 0:f7f1f0d76dd6 577 if (was_messageHTTPrelativePath_ok)
XinZhangMS 0:f7f1f0d76dd6 578 {
XinZhangMS 0:f7f1f0d76dd6 579 result->iotHubClientHandle = iotHubClientHandle;
XinZhangMS 0:f7f1f0d76dd6 580 was_eventHTTPrequestHeaders_ok = create_eventHTTPrequestHeaders(result, device->deviceId, was_x509_ok);
XinZhangMS 0:f7f1f0d76dd6 581 }
XinZhangMS 0:f7f1f0d76dd6 582 else
XinZhangMS 0:f7f1f0d76dd6 583 {
XinZhangMS 0:f7f1f0d76dd6 584 was_eventHTTPrequestHeaders_ok = false;
XinZhangMS 0:f7f1f0d76dd6 585 }
XinZhangMS 0:f7f1f0d76dd6 586 bool was_messageHTTPrequestHeaders_ok = was_eventHTTPrequestHeaders_ok && create_messageHTTPrequestHeaders(result, was_x509_ok);
XinZhangMS 0:f7f1f0d76dd6 587 bool was_abandonHTTPrelativePathBegin_ok = was_messageHTTPrequestHeaders_ok && create_abandonHTTPrelativePathBegin(result, device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 588
XinZhangMS 0:f7f1f0d76dd6 589 if (was_x509_ok)
XinZhangMS 0:f7f1f0d76dd6 590 {
XinZhangMS 0:f7f1f0d76dd6 591 result->sasObject = NULL; /**/
XinZhangMS 0:f7f1f0d76dd6 592 was_sasObject_ok = true;
XinZhangMS 0:f7f1f0d76dd6 593 }
XinZhangMS 0:f7f1f0d76dd6 594 else
XinZhangMS 0:f7f1f0d76dd6 595 {
XinZhangMS 0:f7f1f0d76dd6 596 if (!was_create_deviceSasToken_ok)
XinZhangMS 0:f7f1f0d76dd6 597 {
XinZhangMS 0:f7f1f0d76dd6 598 was_sasObject_ok = was_abandonHTTPrelativePathBegin_ok && create_deviceSASObject(result, handleData->hostName, device->deviceId, device->deviceKey);
XinZhangMS 0:f7f1f0d76dd6 599 }
XinZhangMS 0:f7f1f0d76dd6 600 }
XinZhangMS 0:f7f1f0d76dd6 601
XinZhangMS 0:f7f1f0d76dd6 602 /*Codes_SRS_TRANSPORTMULTITHTTP_17_041: [ IoTHubTransportHttp_Register shall call VECTOR_push_back to store the new device information. ]*/
XinZhangMS 0:f7f1f0d76dd6 603 bool was_list_add_ok = (was_sasObject_ok || was_create_deviceSasToken_ok || was_x509_ok) && (VECTOR_push_back(handleData->perDeviceList, &result, 1) == 0);
XinZhangMS 0:f7f1f0d76dd6 604
XinZhangMS 0:f7f1f0d76dd6 605 if (was_list_add_ok)
XinZhangMS 0:f7f1f0d76dd6 606 {
XinZhangMS 0:f7f1f0d76dd6 607 /*Codes_SRS_TRANSPORTMULTITHTTP_17_043: [ Upon success, IoTHubTransportHttp_Register shall store the transport handle, iotHubClientHandle, and the waitingToSend queue in the device handle return a non-NULL value. ]*/
XinZhangMS 0:f7f1f0d76dd6 608 /*Codes_SRS_TRANSPORTMULTITHTTP_17_040: [ IoTHubTransportHttp_Register shall put event HTTP relative path, message HTTP relative path, event HTTP request headers, message HTTP request headers, abandonHTTPrelativePathBegin, HTTPAPIEX_SAS_HANDLE, and the device handle into a device structure. ]*/
XinZhangMS 0:f7f1f0d76dd6 609 /*Codes_SRS_TRANSPORTMULTITHTTP_17_128: [ IoTHubTransportHttp_Register shall mark this device as unsubscribed. ]*/
XinZhangMS 0:f7f1f0d76dd6 610 result->DoWork_PullMessage = false;
XinZhangMS 0:f7f1f0d76dd6 611 result->isFirstPoll = true;
XinZhangMS 0:f7f1f0d76dd6 612 result->waitingToSend = waitingToSend;
XinZhangMS 0:f7f1f0d76dd6 613 DList_InitializeListHead(&(result->eventConfirmations));
XinZhangMS 0:f7f1f0d76dd6 614 result->transportHandle = (HTTPTRANSPORT_HANDLE_DATA *)handle;
XinZhangMS 0:f7f1f0d76dd6 615 }
XinZhangMS 0:f7f1f0d76dd6 616 else
XinZhangMS 0:f7f1f0d76dd6 617 {
XinZhangMS 0:f7f1f0d76dd6 618 /*Codes_SRS_TRANSPORTMULTITHTTP_17_042: [ If the singlylinkedlist_add fails then IoTHubTransportHttp_Register shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 619 if (was_sasObject_ok) destroy_SASObject(result);
XinZhangMS 0:f7f1f0d76dd6 620 if (was_abandonHTTPrelativePathBegin_ok) destroy_abandonHTTPrelativePathBegin(result);
XinZhangMS 0:f7f1f0d76dd6 621 if (was_messageHTTPrelativePath_ok) destroy_messageHTTPrelativePath(result);
XinZhangMS 0:f7f1f0d76dd6 622 if (was_eventHTTPrequestHeaders_ok) destroy_eventHTTPrequestHeaders(result);
XinZhangMS 0:f7f1f0d76dd6 623 if (was_messageHTTPrequestHeaders_ok) destroy_messageHTTPrequestHeaders(result);
XinZhangMS 0:f7f1f0d76dd6 624 if (was_eventHTTPrelativePath_ok) destroy_eventHTTPrelativePath(result);
XinZhangMS 0:f7f1f0d76dd6 625 if (was_create_deviceId_ok) destroy_deviceId(result);
XinZhangMS 0:f7f1f0d76dd6 626 if (was_create_deviceKey_ok) destroy_deviceKey(result);
XinZhangMS 0:f7f1f0d76dd6 627 if (was_create_deviceSasToken_ok) destroy_deviceSasToken(result);
XinZhangMS 0:f7f1f0d76dd6 628 /*Codes_SRS_TRANSPORTMULTITHTTP_17_039: [ If the allocating the device handle fails then IoTHubTransportHttp_Register shall fail and return NULL. ] */
XinZhangMS 0:f7f1f0d76dd6 629 if (was_resultCreated_ok) free(result);
XinZhangMS 0:f7f1f0d76dd6 630 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 631 }
XinZhangMS 0:f7f1f0d76dd6 632 }
XinZhangMS 0:f7f1f0d76dd6 633
XinZhangMS 0:f7f1f0d76dd6 634 }
XinZhangMS 0:f7f1f0d76dd6 635 return (IOTHUB_DEVICE_HANDLE)result;
XinZhangMS 0:f7f1f0d76dd6 636 }
XinZhangMS 0:f7f1f0d76dd6 637
XinZhangMS 0:f7f1f0d76dd6 638
XinZhangMS 0:f7f1f0d76dd6 639 static void destroy_perDeviceData(HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem)
XinZhangMS 0:f7f1f0d76dd6 640 {
XinZhangMS 0:f7f1f0d76dd6 641 destroy_deviceId(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 642 destroy_deviceKey(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 643 destroy_deviceSas(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 644 destroy_eventHTTPrelativePath(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 645 destroy_messageHTTPrelativePath(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 646 destroy_eventHTTPrequestHeaders(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 647 destroy_messageHTTPrequestHeaders(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 648 destroy_abandonHTTPrelativePathBegin(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 649 destroy_SASObject(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 650 }
XinZhangMS 0:f7f1f0d76dd6 651
XinZhangMS 0:f7f1f0d76dd6 652 static IOTHUB_DEVICE_HANDLE* get_perDeviceDataItem(IOTHUB_DEVICE_HANDLE deviceHandle)
XinZhangMS 0:f7f1f0d76dd6 653 {
XinZhangMS 0:f7f1f0d76dd6 654 HTTPTRANSPORT_PERDEVICE_DATA* deviceHandleData = (HTTPTRANSPORT_PERDEVICE_DATA*)deviceHandle;
XinZhangMS 0:f7f1f0d76dd6 655 IOTHUB_DEVICE_HANDLE* listItem;
XinZhangMS 0:f7f1f0d76dd6 656
XinZhangMS 0:f7f1f0d76dd6 657 HTTPTRANSPORT_HANDLE_DATA* handleData = deviceHandleData->transportHandle;
XinZhangMS 0:f7f1f0d76dd6 658
XinZhangMS 0:f7f1f0d76dd6 659 listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_find_if(handleData->perDeviceList, findDeviceHandle, deviceHandle);
XinZhangMS 0:f7f1f0d76dd6 660 if (listItem == NULL)
XinZhangMS 0:f7f1f0d76dd6 661 {
XinZhangMS 0:f7f1f0d76dd6 662 LogError("device handle not found in transport device list");
XinZhangMS 0:f7f1f0d76dd6 663 listItem = NULL;
XinZhangMS 0:f7f1f0d76dd6 664 }
XinZhangMS 0:f7f1f0d76dd6 665 else
XinZhangMS 0:f7f1f0d76dd6 666 {
XinZhangMS 0:f7f1f0d76dd6 667 /* sucessfully found device in list. */
XinZhangMS 0:f7f1f0d76dd6 668 }
XinZhangMS 0:f7f1f0d76dd6 669
XinZhangMS 0:f7f1f0d76dd6 670 return listItem;
XinZhangMS 0:f7f1f0d76dd6 671 }
XinZhangMS 0:f7f1f0d76dd6 672
XinZhangMS 0:f7f1f0d76dd6 673 static void IoTHubTransportHttp_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
XinZhangMS 0:f7f1f0d76dd6 674 {
XinZhangMS 0:f7f1f0d76dd6 675 if (deviceHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 676 {
XinZhangMS 0:f7f1f0d76dd6 677 /*Codes_SRS_TRANSPORTMULTITHTTP_17_044: [ If deviceHandle is NULL, then IoTHubTransportHttp_Unregister shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 678 LogError("Unregister a NULL device handle");
XinZhangMS 0:f7f1f0d76dd6 679 }
XinZhangMS 0:f7f1f0d76dd6 680 else
XinZhangMS 0:f7f1f0d76dd6 681 {
XinZhangMS 0:f7f1f0d76dd6 682 HTTPTRANSPORT_PERDEVICE_DATA* deviceHandleData = (HTTPTRANSPORT_PERDEVICE_DATA*)deviceHandle;
XinZhangMS 0:f7f1f0d76dd6 683 HTTPTRANSPORT_HANDLE_DATA* handleData = deviceHandleData->transportHandle;
XinZhangMS 0:f7f1f0d76dd6 684 /*Codes_SRS_TRANSPORTMULTITHTTP_17_045: [ IoTHubTransportHttp_Unregister shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
XinZhangMS 0:f7f1f0d76dd6 685 IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(deviceHandle);
XinZhangMS 0:f7f1f0d76dd6 686 if (listItem == NULL)
XinZhangMS 0:f7f1f0d76dd6 687 {
XinZhangMS 0:f7f1f0d76dd6 688 /*Codes_SRS_TRANSPORTMULTITHTTP_17_046: [ If the device structure is not found, then this function shall fail and do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 689 LogError("Device Handle [%p] not found in transport", deviceHandle);
XinZhangMS 0:f7f1f0d76dd6 690 }
XinZhangMS 0:f7f1f0d76dd6 691 else
XinZhangMS 0:f7f1f0d76dd6 692 {
XinZhangMS 0:f7f1f0d76dd6 693 HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
XinZhangMS 0:f7f1f0d76dd6 694
XinZhangMS 0:f7f1f0d76dd6 695 /*Codes_SRS_TRANSPORTMULTITHTTP_17_047: [ IoTHubTransportHttp_Unregister shall free all the resources used in the device structure. ]*/
XinZhangMS 0:f7f1f0d76dd6 696 destroy_perDeviceData(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 697 /*Codes_SRS_TRANSPORTMULTITHTTP_17_048: [ IoTHubTransportHttp_Unregister shall call singlylinkedlist_remove to remove device from devices list. ]*/
XinZhangMS 0:f7f1f0d76dd6 698 VECTOR_erase(handleData->perDeviceList, listItem, 1);
XinZhangMS 0:f7f1f0d76dd6 699 free(deviceHandleData);
XinZhangMS 0:f7f1f0d76dd6 700 }
XinZhangMS 0:f7f1f0d76dd6 701 }
XinZhangMS 0:f7f1f0d76dd6 702
XinZhangMS 0:f7f1f0d76dd6 703 return;
XinZhangMS 0:f7f1f0d76dd6 704 }
XinZhangMS 0:f7f1f0d76dd6 705
XinZhangMS 0:f7f1f0d76dd6 706 /*Codes_SRS_TRANSPORTMULTITHTTP_17_005: [If config->upperConfig->protocolGatewayHostName is NULL, `IoTHubTransportHttp_Create` shall create an immutable string (further called hostname) containing `config->transportConfig->iotHubName + config->transportConfig->iotHubSuffix`.] */
XinZhangMS 0:f7f1f0d76dd6 707 /*Codes_SRS_TRANSPORTMULTITHTTP_20_001: [If config->upperConfig->protocolGatewayHostName is not NULL, IoTHubTransportHttp_Create shall use it as hostname] */
XinZhangMS 0:f7f1f0d76dd6 708 static void destroy_hostName(HTTPTRANSPORT_HANDLE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 709 {
XinZhangMS 0:f7f1f0d76dd6 710 STRING_delete(handleData->hostName);
XinZhangMS 0:f7f1f0d76dd6 711 handleData->hostName = NULL;
XinZhangMS 0:f7f1f0d76dd6 712 }
XinZhangMS 0:f7f1f0d76dd6 713
XinZhangMS 0:f7f1f0d76dd6 714 static bool create_hostName(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
XinZhangMS 0:f7f1f0d76dd6 715 {
XinZhangMS 0:f7f1f0d76dd6 716 bool result;
XinZhangMS 0:f7f1f0d76dd6 717 if (config->upperConfig->protocolGatewayHostName != NULL)
XinZhangMS 0:f7f1f0d76dd6 718 {
XinZhangMS 0:f7f1f0d76dd6 719 /*Codes_SRS_TRANSPORTMULTITHTTP_20_001: [If config->upperConfig->protocolGatewayHostName is not NULL, IoTHubTransportHttp_Create shall use it as hostname] */
XinZhangMS 0:f7f1f0d76dd6 720 handleData->hostName = STRING_construct(config->upperConfig->protocolGatewayHostName);
XinZhangMS 0:f7f1f0d76dd6 721 result = (handleData->hostName != NULL);
XinZhangMS 0:f7f1f0d76dd6 722 }
XinZhangMS 0:f7f1f0d76dd6 723 else
XinZhangMS 0:f7f1f0d76dd6 724 {
XinZhangMS 0:f7f1f0d76dd6 725 /*Codes_SRS_TRANSPORTMULTITHTTP_17_005: [If config->upperConfig->protocolGatewayHostName is NULL, `IoTHubTransportHttp_Create` shall create an immutable string (further called hostname) containing `config->transportConfig->iotHubName + config->transportConfig->iotHubSuffix`.] */
XinZhangMS 0:f7f1f0d76dd6 726 handleData->hostName = STRING_construct(config->upperConfig->iotHubName);
XinZhangMS 0:f7f1f0d76dd6 727
XinZhangMS 0:f7f1f0d76dd6 728 if (handleData->hostName == NULL)
XinZhangMS 0:f7f1f0d76dd6 729 {
XinZhangMS 0:f7f1f0d76dd6 730 result = false;
XinZhangMS 0:f7f1f0d76dd6 731 }
XinZhangMS 0:f7f1f0d76dd6 732 else
XinZhangMS 0:f7f1f0d76dd6 733 {
XinZhangMS 0:f7f1f0d76dd6 734 if ((STRING_concat(handleData->hostName, ".") != 0) ||
XinZhangMS 0:f7f1f0d76dd6 735 (STRING_concat(handleData->hostName, config->upperConfig->iotHubSuffix) != 0))
XinZhangMS 0:f7f1f0d76dd6 736 {
XinZhangMS 0:f7f1f0d76dd6 737 /*Codes_SRS_TRANSPORTMULTITHTTP_17_006: [ If creating the hostname fails then IoTHubTransportHttp_Create shall fail and return NULL. ] */
XinZhangMS 0:f7f1f0d76dd6 738 destroy_hostName(handleData);
XinZhangMS 0:f7f1f0d76dd6 739 result = false;
XinZhangMS 0:f7f1f0d76dd6 740 }
XinZhangMS 0:f7f1f0d76dd6 741 else
XinZhangMS 0:f7f1f0d76dd6 742 {
XinZhangMS 0:f7f1f0d76dd6 743 result = true;
XinZhangMS 0:f7f1f0d76dd6 744 }
XinZhangMS 0:f7f1f0d76dd6 745 }
XinZhangMS 0:f7f1f0d76dd6 746 }
XinZhangMS 0:f7f1f0d76dd6 747 return result;
XinZhangMS 0:f7f1f0d76dd6 748 }
XinZhangMS 0:f7f1f0d76dd6 749
XinZhangMS 0:f7f1f0d76dd6 750 /*Codes_SRS_TRANSPORTMULTITHTTP_17_007: [Otherwise, IoTHubTransportHttp_Create shall create a HTTPAPIEX_HANDLE by a call to HTTPAPIEX_Create passing for hostName the hostname so far constructed by IoTHubTransportHttp_Create.]*/
XinZhangMS 0:f7f1f0d76dd6 751 static void destroy_httpApiExHandle(HTTPTRANSPORT_HANDLE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 752 {
XinZhangMS 0:f7f1f0d76dd6 753 HTTPAPIEX_Destroy(handleData->httpApiExHandle);
XinZhangMS 0:f7f1f0d76dd6 754 handleData->httpApiExHandle = NULL;
XinZhangMS 0:f7f1f0d76dd6 755 }
XinZhangMS 0:f7f1f0d76dd6 756
XinZhangMS 0:f7f1f0d76dd6 757 /*Codes_SRS_TRANSPORTMULTITHTTP_17_007: [ IoTHubTransportHttp_Create shall create a HTTPAPIEX_HANDLE by a call to HTTPAPIEX_Create passing for hostName the hostname so far constructed by IoTHubTransportHttp_Create. ]*/
XinZhangMS 0:f7f1f0d76dd6 758 static bool create_httpApiExHandle(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
XinZhangMS 0:f7f1f0d76dd6 759 {
XinZhangMS 0:f7f1f0d76dd6 760 bool result;
XinZhangMS 0:f7f1f0d76dd6 761 (void)config;
XinZhangMS 0:f7f1f0d76dd6 762 handleData->httpApiExHandle = HTTPAPIEX_Create(STRING_c_str(handleData->hostName));
XinZhangMS 0:f7f1f0d76dd6 763 if (handleData->httpApiExHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 764 {
XinZhangMS 0:f7f1f0d76dd6 765 /*Codes_SRS_TRANSPORTMULTITHTTP_17_008: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubTransportHttp_Create shall fail and return NULL. ] */
XinZhangMS 0:f7f1f0d76dd6 766 result = false;
XinZhangMS 0:f7f1f0d76dd6 767 }
XinZhangMS 0:f7f1f0d76dd6 768 else
XinZhangMS 0:f7f1f0d76dd6 769 {
XinZhangMS 0:f7f1f0d76dd6 770 result = true;
XinZhangMS 0:f7f1f0d76dd6 771 }
XinZhangMS 0:f7f1f0d76dd6 772 return result;
XinZhangMS 0:f7f1f0d76dd6 773 }
XinZhangMS 0:f7f1f0d76dd6 774
XinZhangMS 0:f7f1f0d76dd6 775 static void destroy_perDeviceList(HTTPTRANSPORT_HANDLE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 776 {
XinZhangMS 0:f7f1f0d76dd6 777 VECTOR_destroy(handleData->perDeviceList);
XinZhangMS 0:f7f1f0d76dd6 778 handleData->perDeviceList = NULL;
XinZhangMS 0:f7f1f0d76dd6 779 }
XinZhangMS 0:f7f1f0d76dd6 780
XinZhangMS 0:f7f1f0d76dd6 781 /*Codes_SRS_TRANSPORTMULTITHTTP_17_009: [ IoTHubTransportHttp_Create shall call singlylinkedlist_create to create a list of registered devices. ]*/
XinZhangMS 0:f7f1f0d76dd6 782 static bool create_perDeviceList(HTTPTRANSPORT_HANDLE_DATA* handleData)
XinZhangMS 0:f7f1f0d76dd6 783 {
XinZhangMS 0:f7f1f0d76dd6 784 bool result;
XinZhangMS 0:f7f1f0d76dd6 785 handleData->perDeviceList = VECTOR_create(sizeof(IOTHUB_DEVICE_HANDLE));
XinZhangMS 0:f7f1f0d76dd6 786 if (handleData == NULL || handleData->perDeviceList == NULL)
XinZhangMS 0:f7f1f0d76dd6 787 {
XinZhangMS 0:f7f1f0d76dd6 788 /*Codes_SRS_TRANSPORTMULTITHTTP_17_010: [ If creating the list fails, then IoTHubTransportHttp_Create shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 789 result = false;
XinZhangMS 0:f7f1f0d76dd6 790 }
XinZhangMS 0:f7f1f0d76dd6 791 else
XinZhangMS 0:f7f1f0d76dd6 792 {
XinZhangMS 0:f7f1f0d76dd6 793 result = true;
XinZhangMS 0:f7f1f0d76dd6 794 }
XinZhangMS 0:f7f1f0d76dd6 795 return result;
XinZhangMS 0:f7f1f0d76dd6 796 }
XinZhangMS 0:f7f1f0d76dd6 797
XinZhangMS 0:f7f1f0d76dd6 798
XinZhangMS 0:f7f1f0d76dd6 799 static TRANSPORT_LL_HANDLE IoTHubTransportHttp_Create(const IOTHUBTRANSPORT_CONFIG* config)
XinZhangMS 0:f7f1f0d76dd6 800 {
XinZhangMS 0:f7f1f0d76dd6 801 HTTPTRANSPORT_HANDLE_DATA* result;
XinZhangMS 0:f7f1f0d76dd6 802 if (config == NULL)
XinZhangMS 0:f7f1f0d76dd6 803 {
XinZhangMS 0:f7f1f0d76dd6 804 /*Codes_SRS_TRANSPORTMULTITHTTP_17_001: [If parameter config is NULL, then IoTHubTransportHttp_Create shall return NULL.]*/
XinZhangMS 0:f7f1f0d76dd6 805 LogError("invalid arg (configuration is missing)");
XinZhangMS 0:f7f1f0d76dd6 806 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 807 }
XinZhangMS 0:f7f1f0d76dd6 808 else if (config->upperConfig == NULL)
XinZhangMS 0:f7f1f0d76dd6 809 {
XinZhangMS 0:f7f1f0d76dd6 810 /*Codes_SRS_TRANSPORTMULTITHTTP_17_002: [ If field transportConfig is NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 811 LogError("invalid arg (upperConfig is NULL)");
XinZhangMS 0:f7f1f0d76dd6 812 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 813 }
XinZhangMS 0:f7f1f0d76dd6 814 else if (config->upperConfig->protocol == NULL)
XinZhangMS 0:f7f1f0d76dd6 815 {
XinZhangMS 0:f7f1f0d76dd6 816 /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 817 LogError("invalid arg (protocol is NULL)");
XinZhangMS 0:f7f1f0d76dd6 818 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 819 }
XinZhangMS 0:f7f1f0d76dd6 820 else if (config->upperConfig->iotHubName == NULL)
XinZhangMS 0:f7f1f0d76dd6 821 {
XinZhangMS 0:f7f1f0d76dd6 822 /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 823 LogError("invalid arg (iotHubName is NULL)");
XinZhangMS 0:f7f1f0d76dd6 824 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 825 }
XinZhangMS 0:f7f1f0d76dd6 826 else if (config->upperConfig->iotHubSuffix == NULL)
XinZhangMS 0:f7f1f0d76dd6 827 {
XinZhangMS 0:f7f1f0d76dd6 828 /*Codes_SRS_TRANSPORTMULTITHTTP_17_003: [ If fields protocol, iotHubName or iotHubSuffix in transportConfig are NULL, then IoTHubTransportHttp_Create shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 829 LogError("invalid arg (iotHubSuffix is NULL)");
XinZhangMS 0:f7f1f0d76dd6 830 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 831 }
XinZhangMS 0:f7f1f0d76dd6 832 else
XinZhangMS 0:f7f1f0d76dd6 833 {
XinZhangMS 0:f7f1f0d76dd6 834 /*Codes_SRS_TRANSPORTMULTITHTTP_17_130: [ IoTHubTransportHttp_Create shall allocate memory for the handle. ]*/
XinZhangMS 0:f7f1f0d76dd6 835 result = (HTTPTRANSPORT_HANDLE_DATA*)malloc(sizeof(HTTPTRANSPORT_HANDLE_DATA));
XinZhangMS 0:f7f1f0d76dd6 836 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 837 {
XinZhangMS 0:f7f1f0d76dd6 838 /*Codes_SRS_TRANSPORTMULTITHTTP_17_131: [ If allocation fails, IoTHubTransportHttp_Create shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 839 LogError("unable to malloc");
XinZhangMS 0:f7f1f0d76dd6 840 }
XinZhangMS 0:f7f1f0d76dd6 841 else
XinZhangMS 0:f7f1f0d76dd6 842 {
XinZhangMS 0:f7f1f0d76dd6 843 bool was_hostName_ok = create_hostName(result, config);
XinZhangMS 0:f7f1f0d76dd6 844 bool was_httpApiExHandle_ok = was_hostName_ok && create_httpApiExHandle(result, config);
XinZhangMS 0:f7f1f0d76dd6 845 bool was_perDeviceList_ok = was_httpApiExHandle_ok && create_perDeviceList(result);
XinZhangMS 0:f7f1f0d76dd6 846
XinZhangMS 0:f7f1f0d76dd6 847
XinZhangMS 0:f7f1f0d76dd6 848 if (was_perDeviceList_ok)
XinZhangMS 0:f7f1f0d76dd6 849 {
XinZhangMS 0:f7f1f0d76dd6 850 /*Codes_SRS_TRANSPORTMULTITHTTP_17_011: [ Otherwise, IoTHubTransportHttp_Create shall succeed and return a non-NULL value. ]*/
XinZhangMS 0:f7f1f0d76dd6 851 result->doBatchedTransfers = false;
XinZhangMS 0:f7f1f0d76dd6 852 result->getMinimumPollingTime = DEFAULT_GETMINIMUMPOLLINGTIME;
XinZhangMS 0:f7f1f0d76dd6 853 }
XinZhangMS 0:f7f1f0d76dd6 854 else
XinZhangMS 0:f7f1f0d76dd6 855 {
XinZhangMS 0:f7f1f0d76dd6 856 if (was_httpApiExHandle_ok) destroy_httpApiExHandle(result);
XinZhangMS 0:f7f1f0d76dd6 857 if (was_hostName_ok) destroy_hostName(result);
XinZhangMS 0:f7f1f0d76dd6 858
XinZhangMS 0:f7f1f0d76dd6 859 free(result);
XinZhangMS 0:f7f1f0d76dd6 860 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 861 }
XinZhangMS 0:f7f1f0d76dd6 862 }
XinZhangMS 0:f7f1f0d76dd6 863 }
XinZhangMS 0:f7f1f0d76dd6 864 return result;
XinZhangMS 0:f7f1f0d76dd6 865 }
XinZhangMS 0:f7f1f0d76dd6 866
XinZhangMS 0:f7f1f0d76dd6 867 static void IoTHubTransportHttp_Destroy(TRANSPORT_LL_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 868 {
XinZhangMS 0:f7f1f0d76dd6 869 /*Codes_SRS_TRANSPORTMULTITHTTP_17_012: [ IoTHubTransportHttp_Destroy shall do nothing is handle is NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 870 if (handle != NULL)
XinZhangMS 0:f7f1f0d76dd6 871 {
XinZhangMS 0:f7f1f0d76dd6 872 HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 873 IOTHUB_DEVICE_HANDLE* listItem;
XinZhangMS 0:f7f1f0d76dd6 874
XinZhangMS 0:f7f1f0d76dd6 875 size_t deviceListSize = VECTOR_size(handleData->perDeviceList);
XinZhangMS 0:f7f1f0d76dd6 876
XinZhangMS 0:f7f1f0d76dd6 877 /*Codes_SRS_TRANSPORTMULTITHTTP_17_013: [ Otherwise, IoTHubTransportHttp_Destroy shall free all the resources currently in use. ]*/
XinZhangMS 0:f7f1f0d76dd6 878 for (size_t i = 0; i < deviceListSize; i++)
XinZhangMS 0:f7f1f0d76dd6 879 {
XinZhangMS 0:f7f1f0d76dd6 880 listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_element(handleData->perDeviceList, i);
XinZhangMS 0:f7f1f0d76dd6 881 HTTPTRANSPORT_PERDEVICE_DATA* perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA*)(*listItem);
XinZhangMS 0:f7f1f0d76dd6 882 destroy_perDeviceData(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 883 free(perDeviceItem);
XinZhangMS 0:f7f1f0d76dd6 884 }
XinZhangMS 0:f7f1f0d76dd6 885
XinZhangMS 0:f7f1f0d76dd6 886 destroy_hostName((HTTPTRANSPORT_HANDLE_DATA *)handle);
XinZhangMS 0:f7f1f0d76dd6 887 destroy_httpApiExHandle((HTTPTRANSPORT_HANDLE_DATA *)handle);
XinZhangMS 0:f7f1f0d76dd6 888 destroy_perDeviceList((HTTPTRANSPORT_HANDLE_DATA *)handle);
XinZhangMS 0:f7f1f0d76dd6 889 free(handle);
XinZhangMS 0:f7f1f0d76dd6 890 }
XinZhangMS 0:f7f1f0d76dd6 891 }
XinZhangMS 0:f7f1f0d76dd6 892
XinZhangMS 0:f7f1f0d76dd6 893 static int IoTHubTransportHttp_Subscribe(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 894 {
XinZhangMS 0:f7f1f0d76dd6 895 int result;
XinZhangMS 0:f7f1f0d76dd6 896 if (handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 897 {
XinZhangMS 0:f7f1f0d76dd6 898 /*Codes_SRS_TRANSPORTMULTITHTTP_17_103: [ If parameter deviceHandle is NULL then IoTHubTransportHttp_Subscribe shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 899 LogError("invalid arg passed to IoTHubTransportHttp_Subscribe");
XinZhangMS 0:f7f1f0d76dd6 900 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 901 }
XinZhangMS 0:f7f1f0d76dd6 902 else
XinZhangMS 0:f7f1f0d76dd6 903 {
XinZhangMS 0:f7f1f0d76dd6 904 /*Codes_SRS_TRANSPORTMULTITHTTP_17_104: [ IoTHubTransportHttp_Subscribe shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
XinZhangMS 0:f7f1f0d76dd6 905 IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
XinZhangMS 0:f7f1f0d76dd6 906
XinZhangMS 0:f7f1f0d76dd6 907 if (listItem == NULL)
XinZhangMS 0:f7f1f0d76dd6 908 {
XinZhangMS 0:f7f1f0d76dd6 909 /*Codes_SRS_TRANSPORTMULTITHTTP_17_105: [ If the device structure is not found, then this function shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 910 LogError("did not find device in transport handle");
XinZhangMS 0:f7f1f0d76dd6 911 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 912 }
XinZhangMS 0:f7f1f0d76dd6 913 else
XinZhangMS 0:f7f1f0d76dd6 914 {
XinZhangMS 0:f7f1f0d76dd6 915 HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem;
XinZhangMS 0:f7f1f0d76dd6 916
XinZhangMS 0:f7f1f0d76dd6 917 perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
XinZhangMS 0:f7f1f0d76dd6 918 /*Codes_SRS_TRANSPORTMULTITHTTP_17_106: [ Otherwise, IoTHubTransportHttp_Subscribe shall set the device so that subsequent calls to DoWork should execute HTTP requests. ]*/
XinZhangMS 0:f7f1f0d76dd6 919 perDeviceItem->DoWork_PullMessage = true;
XinZhangMS 0:f7f1f0d76dd6 920 }
XinZhangMS 0:f7f1f0d76dd6 921 result = 0;
XinZhangMS 0:f7f1f0d76dd6 922 }
XinZhangMS 0:f7f1f0d76dd6 923 return result;
XinZhangMS 0:f7f1f0d76dd6 924 }
XinZhangMS 0:f7f1f0d76dd6 925
XinZhangMS 0:f7f1f0d76dd6 926 static void IoTHubTransportHttp_Unsubscribe(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 927 {
XinZhangMS 0:f7f1f0d76dd6 928 /*Codes_SRS_TRANSPORTMULTITHTTP_17_107: [ If parameter deviceHandle is NULL then IoTHubTransportHttp_Unsubscribe shall fail do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 929 if (handle != NULL)
XinZhangMS 0:f7f1f0d76dd6 930 {
XinZhangMS 0:f7f1f0d76dd6 931 /*Codes_SRS_TRANSPORTMULTITHTTP_17_108: [ IoTHubTransportHttp_Unsubscribe shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
XinZhangMS 0:f7f1f0d76dd6 932 IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
XinZhangMS 0:f7f1f0d76dd6 933 /*Codes_SRS_TRANSPORTMULTITHTTP_17_109: [ If the device structure is not found, then this function shall fail and do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 934 if (listItem != NULL)
XinZhangMS 0:f7f1f0d76dd6 935 {
XinZhangMS 0:f7f1f0d76dd6 936 HTTPTRANSPORT_PERDEVICE_DATA * perDeviceItem = (HTTPTRANSPORT_PERDEVICE_DATA *)(*listItem);
XinZhangMS 0:f7f1f0d76dd6 937 /*Codes_SRS_TRANSPORTMULTITHTTP_17_110: [ Otherwise, IoTHubTransportHttp_Subscribe shall set the device so that subsequent calls to DoWork shall not execute HTTP requests. ]*/
XinZhangMS 0:f7f1f0d76dd6 938 perDeviceItem->DoWork_PullMessage = false;
XinZhangMS 0:f7f1f0d76dd6 939 }
XinZhangMS 0:f7f1f0d76dd6 940 else
XinZhangMS 0:f7f1f0d76dd6 941 {
XinZhangMS 0:f7f1f0d76dd6 942 LogError("Device not found to unsuscribe.");
XinZhangMS 0:f7f1f0d76dd6 943 }
XinZhangMS 0:f7f1f0d76dd6 944 }
XinZhangMS 0:f7f1f0d76dd6 945 else
XinZhangMS 0:f7f1f0d76dd6 946 {
XinZhangMS 0:f7f1f0d76dd6 947 LogError("Null handle passed to Unsuscribe.");
XinZhangMS 0:f7f1f0d76dd6 948 }
XinZhangMS 0:f7f1f0d76dd6 949 }
XinZhangMS 0:f7f1f0d76dd6 950
XinZhangMS 0:f7f1f0d76dd6 951 static int IoTHubTransportHttp_Subscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 952 {
XinZhangMS 0:f7f1f0d76dd6 953 /*Codes_SRS_TRANSPORTMULTITHTTP_02_003: [ IoTHubTransportHttp_Subscribe_DeviceTwin shall return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 954 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 955 int result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 956 LogError("IoTHubTransportHttp_Subscribe_DeviceTwin Not supported");
XinZhangMS 0:f7f1f0d76dd6 957 return result;
XinZhangMS 0:f7f1f0d76dd6 958 }
XinZhangMS 0:f7f1f0d76dd6 959
XinZhangMS 0:f7f1f0d76dd6 960 static void IoTHubTransportHttp_Unsubscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 961 {
XinZhangMS 0:f7f1f0d76dd6 962 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 963 /*Codes_SRS_TRANSPORTMULTITHTTP_02_004: [ IoTHubTransportHttp_Unsubscribe_DeviceTwin shall return ]*/
XinZhangMS 0:f7f1f0d76dd6 964 LogError("IoTHubTransportHttp_Unsubscribe_DeviceTwin Not supported");
XinZhangMS 0:f7f1f0d76dd6 965 }
XinZhangMS 0:f7f1f0d76dd6 966
XinZhangMS 0:f7f1f0d76dd6 967 static int IoTHubTransportHttp_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 968 {
XinZhangMS 0:f7f1f0d76dd6 969 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 970 int result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 971 LogError("not implemented (yet)");
XinZhangMS 0:f7f1f0d76dd6 972 return result;
XinZhangMS 0:f7f1f0d76dd6 973 }
XinZhangMS 0:f7f1f0d76dd6 974
XinZhangMS 0:f7f1f0d76dd6 975 static void IoTHubTransportHttp_Unsubscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 976 {
XinZhangMS 0:f7f1f0d76dd6 977 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 978 LogError("not implemented (yet)");
XinZhangMS 0:f7f1f0d76dd6 979 }
XinZhangMS 0:f7f1f0d76dd6 980
XinZhangMS 0:f7f1f0d76dd6 981 static int IoTHubTransportHttp_DeviceMethod_Response(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t response_size, int status_response)
XinZhangMS 0:f7f1f0d76dd6 982 {
XinZhangMS 0:f7f1f0d76dd6 983 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 984 (void)methodId;
XinZhangMS 0:f7f1f0d76dd6 985 (void)response;
XinZhangMS 0:f7f1f0d76dd6 986 (void)response_size;
XinZhangMS 0:f7f1f0d76dd6 987 (void)status_response;
XinZhangMS 0:f7f1f0d76dd6 988 LogError("not implemented (yet)");
XinZhangMS 0:f7f1f0d76dd6 989 return __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 990 }
XinZhangMS 0:f7f1f0d76dd6 991
XinZhangMS 0:f7f1f0d76dd6 992 /*produces a representation of the properties, if they exist*/
XinZhangMS 0:f7f1f0d76dd6 993 /*if they do not exist, produces ""*/
XinZhangMS 0:f7f1f0d76dd6 994 static int concat_Properties(STRING_HANDLE existing, MAP_HANDLE map, size_t* propertiesMessageSizeContribution)
XinZhangMS 0:f7f1f0d76dd6 995 {
XinZhangMS 0:f7f1f0d76dd6 996 int result;
XinZhangMS 0:f7f1f0d76dd6 997 const char*const* keys;
XinZhangMS 0:f7f1f0d76dd6 998 const char*const* values;
XinZhangMS 0:f7f1f0d76dd6 999 size_t count;
XinZhangMS 0:f7f1f0d76dd6 1000 if (Map_GetInternals(map, &keys, &values, &count) != MAP_OK)
XinZhangMS 0:f7f1f0d76dd6 1001 {
XinZhangMS 0:f7f1f0d76dd6 1002 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1003 LogError("error while Map_GetInternals");
XinZhangMS 0:f7f1f0d76dd6 1004 }
XinZhangMS 0:f7f1f0d76dd6 1005 else
XinZhangMS 0:f7f1f0d76dd6 1006 {
XinZhangMS 0:f7f1f0d76dd6 1007
XinZhangMS 0:f7f1f0d76dd6 1008 if (count == 0)
XinZhangMS 0:f7f1f0d76dd6 1009 {
XinZhangMS 0:f7f1f0d76dd6 1010 /*Codes_SRS_TRANSPORTMULTITHTTP_17_064: [If IoTHubMessage does not have properties, then "properties":{...} shall be missing from the payload*/
XinZhangMS 0:f7f1f0d76dd6 1011 /*no properties - do nothing with existing*/
XinZhangMS 0:f7f1f0d76dd6 1012 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1013 *propertiesMessageSizeContribution = 0;
XinZhangMS 0:f7f1f0d76dd6 1014 }
XinZhangMS 0:f7f1f0d76dd6 1015 else
XinZhangMS 0:f7f1f0d76dd6 1016 {
XinZhangMS 0:f7f1f0d76dd6 1017 /*Codes_SRS_TRANSPORTMULTITHTTP_17_058: [If IoTHubMessage has properties, then they shall be serialized at the same level as "body" using the following pattern: "properties":{"iothub-app-name1":"value1","iothub-app-name2":"value2*/
XinZhangMS 0:f7f1f0d76dd6 1018 if (STRING_concat(existing, ",\"properties\":") != 0)
XinZhangMS 0:f7f1f0d76dd6 1019 {
XinZhangMS 0:f7f1f0d76dd6 1020 /*go ahead and return it*/
XinZhangMS 0:f7f1f0d76dd6 1021 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1022 LogError("failed STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1023 }
XinZhangMS 0:f7f1f0d76dd6 1024 else if (appendMapToJSON(existing, keys, values, count) != 0)
XinZhangMS 0:f7f1f0d76dd6 1025 {
XinZhangMS 0:f7f1f0d76dd6 1026 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1027 LogError("unable to append the properties");
XinZhangMS 0:f7f1f0d76dd6 1028 }
XinZhangMS 0:f7f1f0d76dd6 1029 else
XinZhangMS 0:f7f1f0d76dd6 1030 {
XinZhangMS 0:f7f1f0d76dd6 1031 /*all is fine*/
XinZhangMS 0:f7f1f0d76dd6 1032 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1033 *propertiesMessageSizeContribution = 0;
XinZhangMS 0:f7f1f0d76dd6 1034 for (i = 0; i < count; i++)
XinZhangMS 0:f7f1f0d76dd6 1035 {
XinZhangMS 0:f7f1f0d76dd6 1036 /*Codes_SRS_TRANSPORTMULTITHTTP_17_063: [Every property name shall add to the message size the length of the property name + the length of the property value + 16 bytes.] */
XinZhangMS 0:f7f1f0d76dd6 1037 *propertiesMessageSizeContribution += (strlen(keys[i]) + strlen(values[i]) + MAXIMUM_PROPERTY_OVERHEAD);
XinZhangMS 0:f7f1f0d76dd6 1038 }
XinZhangMS 0:f7f1f0d76dd6 1039 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1040 }
XinZhangMS 0:f7f1f0d76dd6 1041 }
XinZhangMS 0:f7f1f0d76dd6 1042 }
XinZhangMS 0:f7f1f0d76dd6 1043 return result;
XinZhangMS 0:f7f1f0d76dd6 1044 }
XinZhangMS 0:f7f1f0d76dd6 1045
XinZhangMS 0:f7f1f0d76dd6 1046 /*produces a JSON representation of the map : {"a": "value_of_a","b":"value_of_b"}*/
XinZhangMS 0:f7f1f0d76dd6 1047 static int appendMapToJSON(STRING_HANDLE existing, const char* const* keys, const char* const* values, size_t count) /*under consideration: move to MAP module when it has more than 1 user*/
XinZhangMS 0:f7f1f0d76dd6 1048 {
XinZhangMS 0:f7f1f0d76dd6 1049 int result;
XinZhangMS 0:f7f1f0d76dd6 1050 if (STRING_concat(existing, "{") != 0)
XinZhangMS 0:f7f1f0d76dd6 1051 {
XinZhangMS 0:f7f1f0d76dd6 1052 /*go on and return it*/
XinZhangMS 0:f7f1f0d76dd6 1053 LogError("STRING_construct failed");
XinZhangMS 0:f7f1f0d76dd6 1054 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1055 }
XinZhangMS 0:f7f1f0d76dd6 1056 else
XinZhangMS 0:f7f1f0d76dd6 1057 {
XinZhangMS 0:f7f1f0d76dd6 1058 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1059 for (i = 0; i < count; i++)
XinZhangMS 0:f7f1f0d76dd6 1060 {
XinZhangMS 0:f7f1f0d76dd6 1061 if (!(
XinZhangMS 0:f7f1f0d76dd6 1062 (STRING_concat(existing, (i == 0) ? "\"" IOTHUB_APP_PREFIX : ",\"" IOTHUB_APP_PREFIX) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1063 (STRING_concat(existing, keys[i]) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1064 (STRING_concat(existing, "\":\"") == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1065 (STRING_concat(existing, values[i]) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1066 (STRING_concat(existing, "\"") == 0)
XinZhangMS 0:f7f1f0d76dd6 1067 ))
XinZhangMS 0:f7f1f0d76dd6 1068 {
XinZhangMS 0:f7f1f0d76dd6 1069 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1070 break;
XinZhangMS 0:f7f1f0d76dd6 1071 }
XinZhangMS 0:f7f1f0d76dd6 1072 }
XinZhangMS 0:f7f1f0d76dd6 1073
XinZhangMS 0:f7f1f0d76dd6 1074 if (i < count)
XinZhangMS 0:f7f1f0d76dd6 1075 {
XinZhangMS 0:f7f1f0d76dd6 1076 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1077 /*error, let it go through*/
XinZhangMS 0:f7f1f0d76dd6 1078 }
XinZhangMS 0:f7f1f0d76dd6 1079 else if (STRING_concat(existing, "}") != 0)
XinZhangMS 0:f7f1f0d76dd6 1080 {
XinZhangMS 0:f7f1f0d76dd6 1081 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1082 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1083 }
XinZhangMS 0:f7f1f0d76dd6 1084 else
XinZhangMS 0:f7f1f0d76dd6 1085 {
XinZhangMS 0:f7f1f0d76dd6 1086 /*all is fine*/
XinZhangMS 0:f7f1f0d76dd6 1087 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1088 }
XinZhangMS 0:f7f1f0d76dd6 1089 }
XinZhangMS 0:f7f1f0d76dd6 1090 return result;
XinZhangMS 0:f7f1f0d76dd6 1091 }
XinZhangMS 0:f7f1f0d76dd6 1092
XinZhangMS 0:f7f1f0d76dd6 1093 /*makes the following string:{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
XinZhangMS 0:f7f1f0d76dd6 1094 /*return NULL if there was a failure, or a non-NULL STRING_HANDLE that contains the intended data*/
XinZhangMS 0:f7f1f0d76dd6 1095 static STRING_HANDLE make1EventJSONitem(PDLIST_ENTRY item, size_t *messageSizeContribution)
XinZhangMS 0:f7f1f0d76dd6 1096 {
XinZhangMS 0:f7f1f0d76dd6 1097 STRING_HANDLE result; /*temp wants to contain :{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
XinZhangMS 0:f7f1f0d76dd6 1098 IOTHUB_MESSAGE_LIST* message = containingRecord(item, IOTHUB_MESSAGE_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 1099 IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1100
XinZhangMS 0:f7f1f0d76dd6 1101 switch (contentType)
XinZhangMS 0:f7f1f0d76dd6 1102 {
XinZhangMS 0:f7f1f0d76dd6 1103 case IOTHUBMESSAGE_BYTEARRAY:
XinZhangMS 0:f7f1f0d76dd6 1104 {
XinZhangMS 0:f7f1f0d76dd6 1105 result = STRING_construct("{\"body\":\"");
XinZhangMS 0:f7f1f0d76dd6 1106 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 1107 {
XinZhangMS 0:f7f1f0d76dd6 1108 LogError("unable to STRING_construct");
XinZhangMS 0:f7f1f0d76dd6 1109 }
XinZhangMS 0:f7f1f0d76dd6 1110 else
XinZhangMS 0:f7f1f0d76dd6 1111 {
XinZhangMS 0:f7f1f0d76dd6 1112 const unsigned char* source;
XinZhangMS 0:f7f1f0d76dd6 1113 size_t size;
XinZhangMS 0:f7f1f0d76dd6 1114
XinZhangMS 0:f7f1f0d76dd6 1115 if (IoTHubMessage_GetByteArray(message->messageHandle, &source, &size) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1116 {
XinZhangMS 0:f7f1f0d76dd6 1117 LogError("unable to get the data for the message.");
XinZhangMS 0:f7f1f0d76dd6 1118 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1119 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1120 }
XinZhangMS 0:f7f1f0d76dd6 1121 else
XinZhangMS 0:f7f1f0d76dd6 1122 {
XinZhangMS 0:f7f1f0d76dd6 1123 STRING_HANDLE encoded = Base64_Encode_Bytes(source, size);
XinZhangMS 0:f7f1f0d76dd6 1124 if (encoded == NULL)
XinZhangMS 0:f7f1f0d76dd6 1125 {
XinZhangMS 0:f7f1f0d76dd6 1126 LogError("unable to Base64_Encode_Bytes.");
XinZhangMS 0:f7f1f0d76dd6 1127 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1128 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1129 }
XinZhangMS 0:f7f1f0d76dd6 1130 else
XinZhangMS 0:f7f1f0d76dd6 1131 {
XinZhangMS 0:f7f1f0d76dd6 1132 size_t propertiesSize = 0;
XinZhangMS 0:f7f1f0d76dd6 1133 if (!(
XinZhangMS 0:f7f1f0d76dd6 1134 (STRING_concat_with_STRING(result, encoded) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1135 (STRING_concat(result, "\"") == 0) && /*\" because closing value*/
XinZhangMS 0:f7f1f0d76dd6 1136 (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1137 (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
XinZhangMS 0:f7f1f0d76dd6 1138 ))
XinZhangMS 0:f7f1f0d76dd6 1139 {
XinZhangMS 0:f7f1f0d76dd6 1140 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1141 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1142 LogError("unable to STRING_concat_with_STRING.");
XinZhangMS 0:f7f1f0d76dd6 1143 }
XinZhangMS 0:f7f1f0d76dd6 1144 else
XinZhangMS 0:f7f1f0d76dd6 1145 {
XinZhangMS 0:f7f1f0d76dd6 1146 /*all is fine... */
XinZhangMS 0:f7f1f0d76dd6 1147 /*Codes_SRS_TRANSPORTMULTITHTTP_17_062: [The message size is computed from the length of the payload + 384.] */
XinZhangMS 0:f7f1f0d76dd6 1148 *messageSizeContribution = size + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
XinZhangMS 0:f7f1f0d76dd6 1149 }
XinZhangMS 0:f7f1f0d76dd6 1150 STRING_delete(encoded);
XinZhangMS 0:f7f1f0d76dd6 1151 }
XinZhangMS 0:f7f1f0d76dd6 1152 }
XinZhangMS 0:f7f1f0d76dd6 1153 }
XinZhangMS 0:f7f1f0d76dd6 1154 break;
XinZhangMS 0:f7f1f0d76dd6 1155 }
XinZhangMS 0:f7f1f0d76dd6 1156 /*Codes_SRS_TRANSPORTMULTITHTTP_17_057: [If a messages to be send has type IOTHUBMESSAGE_STRING, then its serialization shall be {"body":"JSON encoding of the string", "base64Encoded":false}] */
XinZhangMS 0:f7f1f0d76dd6 1157 case IOTHUBMESSAGE_STRING:
XinZhangMS 0:f7f1f0d76dd6 1158 {
XinZhangMS 0:f7f1f0d76dd6 1159 result = STRING_construct("{\"body\":");
XinZhangMS 0:f7f1f0d76dd6 1160 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 1161 {
XinZhangMS 0:f7f1f0d76dd6 1162 LogError("unable to STRING_construct");
XinZhangMS 0:f7f1f0d76dd6 1163 }
XinZhangMS 0:f7f1f0d76dd6 1164 else
XinZhangMS 0:f7f1f0d76dd6 1165 {
XinZhangMS 0:f7f1f0d76dd6 1166 const char* source = IoTHubMessage_GetString(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1167 if (source == NULL)
XinZhangMS 0:f7f1f0d76dd6 1168 {
XinZhangMS 0:f7f1f0d76dd6 1169 LogError("unable to IoTHubMessage_GetString");
XinZhangMS 0:f7f1f0d76dd6 1170 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1171 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1172 }
XinZhangMS 0:f7f1f0d76dd6 1173 else
XinZhangMS 0:f7f1f0d76dd6 1174 {
XinZhangMS 0:f7f1f0d76dd6 1175 STRING_HANDLE asJson = STRING_new_JSON(source);
XinZhangMS 0:f7f1f0d76dd6 1176 if (asJson == NULL)
XinZhangMS 0:f7f1f0d76dd6 1177 {
XinZhangMS 0:f7f1f0d76dd6 1178 LogError("unable to STRING_new_JSON");
XinZhangMS 0:f7f1f0d76dd6 1179 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1180 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1181 }
XinZhangMS 0:f7f1f0d76dd6 1182 else
XinZhangMS 0:f7f1f0d76dd6 1183 {
XinZhangMS 0:f7f1f0d76dd6 1184 size_t propertiesSize = 0;
XinZhangMS 0:f7f1f0d76dd6 1185 if (!(
XinZhangMS 0:f7f1f0d76dd6 1186 (STRING_concat_with_STRING(result, asJson) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1187 (STRING_concat(result, ",\"base64Encoded\":false") == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1188 (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1189 (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
XinZhangMS 0:f7f1f0d76dd6 1190 ))
XinZhangMS 0:f7f1f0d76dd6 1191 {
XinZhangMS 0:f7f1f0d76dd6 1192 LogError("unable to STRING_concat_with_STRING");
XinZhangMS 0:f7f1f0d76dd6 1193 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 1194 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1195 }
XinZhangMS 0:f7f1f0d76dd6 1196 else
XinZhangMS 0:f7f1f0d76dd6 1197 {
XinZhangMS 0:f7f1f0d76dd6 1198 /*result has the intended content*/
XinZhangMS 0:f7f1f0d76dd6 1199 /*Codes_SRS_TRANSPORTMULTITHTTP_17_062: [The message size is computed from the length of the payload + 384.] */
XinZhangMS 0:f7f1f0d76dd6 1200 *messageSizeContribution = strlen(source) + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
XinZhangMS 0:f7f1f0d76dd6 1201 }
XinZhangMS 0:f7f1f0d76dd6 1202 STRING_delete(asJson);
XinZhangMS 0:f7f1f0d76dd6 1203 }
XinZhangMS 0:f7f1f0d76dd6 1204 }
XinZhangMS 0:f7f1f0d76dd6 1205 }
XinZhangMS 0:f7f1f0d76dd6 1206 break;
XinZhangMS 0:f7f1f0d76dd6 1207 }
XinZhangMS 0:f7f1f0d76dd6 1208 default:
XinZhangMS 0:f7f1f0d76dd6 1209 {
XinZhangMS 0:f7f1f0d76dd6 1210 LogError("an unknown message type was encountered (%d)", contentType);
XinZhangMS 0:f7f1f0d76dd6 1211 result = NULL; /*unknown message type*/
XinZhangMS 0:f7f1f0d76dd6 1212 break;
XinZhangMS 0:f7f1f0d76dd6 1213 }
XinZhangMS 0:f7f1f0d76dd6 1214 }
XinZhangMS 0:f7f1f0d76dd6 1215 return result;
XinZhangMS 0:f7f1f0d76dd6 1216 }
XinZhangMS 0:f7f1f0d76dd6 1217
XinZhangMS 0:f7f1f0d76dd6 1218 #define MAKE_PAYLOAD_RESULT_VALUES \
XinZhangMS 0:f7f1f0d76dd6 1219 MAKE_PAYLOAD_OK, /*returned when there is a payload to be later send by HTTP*/ \
XinZhangMS 0:f7f1f0d76dd6 1220 MAKE_PAYLOAD_NO_ITEMS, /*returned when there are no items to be send*/ \
XinZhangMS 0:f7f1f0d76dd6 1221 MAKE_PAYLOAD_ERROR, /*returned when there were errors*/ \
XinZhangMS 0:f7f1f0d76dd6 1222 MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT /*returned when the first item doesn't fit*/
XinZhangMS 0:f7f1f0d76dd6 1223
XinZhangMS 0:f7f1f0d76dd6 1224 DEFINE_ENUM(MAKE_PAYLOAD_RESULT, MAKE_PAYLOAD_RESULT_VALUES);
XinZhangMS 0:f7f1f0d76dd6 1225
XinZhangMS 0:f7f1f0d76dd6 1226 /*this function assembles several {"body":"base64 encoding of the message content"," base64Encoded": true} into 1 payload*/
XinZhangMS 0:f7f1f0d76dd6 1227 /*Codes_SRS_TRANSPORTMULTITHTTP_17_056: [IoTHubTransportHttp_DoWork shall build the following string:[{"body":"base64 encoding of the message1 content"},{"body":"base64 encoding of the message2 content"}...]]*/
XinZhangMS 0:f7f1f0d76dd6 1228 static MAKE_PAYLOAD_RESULT makePayload(HTTPTRANSPORT_PERDEVICE_DATA* deviceData, STRING_HANDLE* payload)
XinZhangMS 0:f7f1f0d76dd6 1229 {
XinZhangMS 0:f7f1f0d76dd6 1230 MAKE_PAYLOAD_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1231 size_t allMessagesSize = 0;
XinZhangMS 0:f7f1f0d76dd6 1232 *payload = STRING_construct("[");
XinZhangMS 0:f7f1f0d76dd6 1233 if (*payload == NULL)
XinZhangMS 0:f7f1f0d76dd6 1234 {
XinZhangMS 0:f7f1f0d76dd6 1235 LogError("unable to STRING_construct");
XinZhangMS 0:f7f1f0d76dd6 1236 result = MAKE_PAYLOAD_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1237 }
XinZhangMS 0:f7f1f0d76dd6 1238 else
XinZhangMS 0:f7f1f0d76dd6 1239 {
XinZhangMS 0:f7f1f0d76dd6 1240 bool isFirst = true;
XinZhangMS 0:f7f1f0d76dd6 1241 PDLIST_ENTRY actual;
XinZhangMS 0:f7f1f0d76dd6 1242 bool keepGoing = true; /*keepGoing gets sometimes to false from within the loop*/
XinZhangMS 0:f7f1f0d76dd6 1243 /*either all the items enter the list or only some*/
XinZhangMS 0:f7f1f0d76dd6 1244 result = MAKE_PAYLOAD_OK; /*optimistically initializing it*/
XinZhangMS 0:f7f1f0d76dd6 1245 while (keepGoing && ((actual = deviceData->waitingToSend->Flink) != deviceData->waitingToSend))
XinZhangMS 0:f7f1f0d76dd6 1246 {
XinZhangMS 0:f7f1f0d76dd6 1247 size_t messageSize;
XinZhangMS 0:f7f1f0d76dd6 1248 STRING_HANDLE temp = make1EventJSONitem(actual, &messageSize);
XinZhangMS 0:f7f1f0d76dd6 1249 if (isFirst)
XinZhangMS 0:f7f1f0d76dd6 1250 {
XinZhangMS 0:f7f1f0d76dd6 1251 isFirst = false;
XinZhangMS 0:f7f1f0d76dd6 1252 /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
XinZhangMS 0:f7f1f0d76dd6 1253 if (temp == NULL) /*first item failed to create, nothing to send*/
XinZhangMS 0:f7f1f0d76dd6 1254 {
XinZhangMS 0:f7f1f0d76dd6 1255 result = MAKE_PAYLOAD_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1256 STRING_delete(*payload);
XinZhangMS 0:f7f1f0d76dd6 1257 *payload = NULL;
XinZhangMS 0:f7f1f0d76dd6 1258 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1259 }
XinZhangMS 0:f7f1f0d76dd6 1260 else
XinZhangMS 0:f7f1f0d76dd6 1261 {
XinZhangMS 0:f7f1f0d76dd6 1262 /*Codes_SRS_TRANSPORTMULTITHTTP_17_065: [If the oldest message in waitingToSend causes the message size to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClientCore_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_BATCHSTATE_FAILED.]*/
XinZhangMS 0:f7f1f0d76dd6 1263 /*Codes_SRS_TRANSPORTMULTITHTTP_17_061: [The message size shall be limited to 255KB - 1 byte.]*/
XinZhangMS 0:f7f1f0d76dd6 1264 if (messageSize > MAXIMUM_MESSAGE_SIZE)
XinZhangMS 0:f7f1f0d76dd6 1265 {
XinZhangMS 0:f7f1f0d76dd6 1266 PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1267 DList_InsertTailList(&(deviceData->eventConfirmations), head);
XinZhangMS 0:f7f1f0d76dd6 1268 result = MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT;
XinZhangMS 0:f7f1f0d76dd6 1269 STRING_delete(*payload);
XinZhangMS 0:f7f1f0d76dd6 1270 *payload = NULL;
XinZhangMS 0:f7f1f0d76dd6 1271 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1272 }
XinZhangMS 0:f7f1f0d76dd6 1273 else
XinZhangMS 0:f7f1f0d76dd6 1274 {
XinZhangMS 0:f7f1f0d76dd6 1275 if (STRING_concat_with_STRING(*payload, temp) != 0)
XinZhangMS 0:f7f1f0d76dd6 1276 {
XinZhangMS 0:f7f1f0d76dd6 1277 /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
XinZhangMS 0:f7f1f0d76dd6 1278 result = MAKE_PAYLOAD_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1279 STRING_delete(*payload);
XinZhangMS 0:f7f1f0d76dd6 1280 *payload = NULL;
XinZhangMS 0:f7f1f0d76dd6 1281 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1282 }
XinZhangMS 0:f7f1f0d76dd6 1283 else
XinZhangMS 0:f7f1f0d76dd6 1284 {
XinZhangMS 0:f7f1f0d76dd6 1285 /*first item was put nicely in the payload*/
XinZhangMS 0:f7f1f0d76dd6 1286 PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1287 DList_InsertTailList(&(deviceData->eventConfirmations), head);
XinZhangMS 0:f7f1f0d76dd6 1288 allMessagesSize += messageSize;
XinZhangMS 0:f7f1f0d76dd6 1289 }
XinZhangMS 0:f7f1f0d76dd6 1290 }
XinZhangMS 0:f7f1f0d76dd6 1291 STRING_delete(temp);
XinZhangMS 0:f7f1f0d76dd6 1292 }
XinZhangMS 0:f7f1f0d76dd6 1293 }
XinZhangMS 0:f7f1f0d76dd6 1294 else
XinZhangMS 0:f7f1f0d76dd6 1295 {
XinZhangMS 0:f7f1f0d76dd6 1296 /*there is at least 1 item already in the payload*/
XinZhangMS 0:f7f1f0d76dd6 1297 if (temp == NULL)
XinZhangMS 0:f7f1f0d76dd6 1298 {
XinZhangMS 0:f7f1f0d76dd6 1299 /*there are multiple payloads encoded, the last one had an internal error, just go with those - closing the payload happens "after the loop"*/
XinZhangMS 0:f7f1f0d76dd6 1300 /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
XinZhangMS 0:f7f1f0d76dd6 1301 result = MAKE_PAYLOAD_OK;
XinZhangMS 0:f7f1f0d76dd6 1302 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1303 }
XinZhangMS 0:f7f1f0d76dd6 1304 else
XinZhangMS 0:f7f1f0d76dd6 1305 {
XinZhangMS 0:f7f1f0d76dd6 1306 if (allMessagesSize + messageSize > MAXIMUM_MESSAGE_SIZE)
XinZhangMS 0:f7f1f0d76dd6 1307 {
XinZhangMS 0:f7f1f0d76dd6 1308 /*this item doesn't make it to the payload, but the payload is valid so far*/
XinZhangMS 0:f7f1f0d76dd6 1309 /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
XinZhangMS 0:f7f1f0d76dd6 1310 result = MAKE_PAYLOAD_OK;
XinZhangMS 0:f7f1f0d76dd6 1311 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1312 }
XinZhangMS 0:f7f1f0d76dd6 1313 else if (STRING_concat_with_STRING(*payload, temp) != 0)
XinZhangMS 0:f7f1f0d76dd6 1314 {
XinZhangMS 0:f7f1f0d76dd6 1315 /*should still send what there is so far...*/
XinZhangMS 0:f7f1f0d76dd6 1316 /*Codes_SRS_TRANSPORTMULTITHTTP_17_066: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
XinZhangMS 0:f7f1f0d76dd6 1317 result = MAKE_PAYLOAD_OK;
XinZhangMS 0:f7f1f0d76dd6 1318 keepGoing = false;
XinZhangMS 0:f7f1f0d76dd6 1319 }
XinZhangMS 0:f7f1f0d76dd6 1320 else
XinZhangMS 0:f7f1f0d76dd6 1321 {
XinZhangMS 0:f7f1f0d76dd6 1322 /*cool, the payload made it there, let's continue... */
XinZhangMS 0:f7f1f0d76dd6 1323 PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1324 DList_InsertTailList(&(deviceData->eventConfirmations), head);
XinZhangMS 0:f7f1f0d76dd6 1325 allMessagesSize += messageSize;
XinZhangMS 0:f7f1f0d76dd6 1326 }
XinZhangMS 0:f7f1f0d76dd6 1327 STRING_delete(temp);
XinZhangMS 0:f7f1f0d76dd6 1328 }
XinZhangMS 0:f7f1f0d76dd6 1329 }
XinZhangMS 0:f7f1f0d76dd6 1330 }
XinZhangMS 0:f7f1f0d76dd6 1331
XinZhangMS 0:f7f1f0d76dd6 1332 /*closing the payload*/
XinZhangMS 0:f7f1f0d76dd6 1333 if (result == MAKE_PAYLOAD_OK)
XinZhangMS 0:f7f1f0d76dd6 1334 {
XinZhangMS 0:f7f1f0d76dd6 1335 ((char*)STRING_c_str(*payload))[STRING_length(*payload) - 1] = ']'; /*TODO - do this in STRING_HANDLE*/
XinZhangMS 0:f7f1f0d76dd6 1336 }
XinZhangMS 0:f7f1f0d76dd6 1337 else
XinZhangMS 0:f7f1f0d76dd6 1338 {
XinZhangMS 0:f7f1f0d76dd6 1339 /*no need to close anything*/
XinZhangMS 0:f7f1f0d76dd6 1340 }
XinZhangMS 0:f7f1f0d76dd6 1341 }
XinZhangMS 0:f7f1f0d76dd6 1342 return result;
XinZhangMS 0:f7f1f0d76dd6 1343 }
XinZhangMS 0:f7f1f0d76dd6 1344
XinZhangMS 0:f7f1f0d76dd6 1345 static void reversePutListBackIn(PDLIST_ENTRY source, PDLIST_ENTRY destination)
XinZhangMS 0:f7f1f0d76dd6 1346 {
XinZhangMS 0:f7f1f0d76dd6 1347 /*this function takes a list, and inserts it in another list. When done in the context of this file, it reverses the effects of a not-able-to-send situation*/
XinZhangMS 0:f7f1f0d76dd6 1348 DList_AppendTailList(destination->Flink, source);
XinZhangMS 0:f7f1f0d76dd6 1349 DList_RemoveEntryList(source);
XinZhangMS 0:f7f1f0d76dd6 1350 DList_InitializeListHead(source);
XinZhangMS 0:f7f1f0d76dd6 1351 }
XinZhangMS 0:f7f1f0d76dd6 1352
XinZhangMS 0:f7f1f0d76dd6 1353 static void DoEvent(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
XinZhangMS 0:f7f1f0d76dd6 1354 {
XinZhangMS 0:f7f1f0d76dd6 1355
XinZhangMS 0:f7f1f0d76dd6 1356 if (DList_IsListEmpty(deviceData->waitingToSend))
XinZhangMS 0:f7f1f0d76dd6 1357 {
XinZhangMS 0:f7f1f0d76dd6 1358 /*Codes_SRS_TRANSPORTMULTITHTTP_17_060: [If the list is empty then IoTHubTransportHttp_DoWork shall proceed to the following action.] */
XinZhangMS 0:f7f1f0d76dd6 1359 }
XinZhangMS 0:f7f1f0d76dd6 1360 else
XinZhangMS 0:f7f1f0d76dd6 1361 {
XinZhangMS 0:f7f1f0d76dd6 1362 /*Codes_SRS_TRANSPORTMULTITHTTP_17_053: [If option SetBatching is true then _Dowork shall send batched event message as specced below.] */
XinZhangMS 0:f7f1f0d76dd6 1363 if (handleData->doBatchedTransfers)
XinZhangMS 0:f7f1f0d76dd6 1364 {
XinZhangMS 0:f7f1f0d76dd6 1365 /*Codes_SRS_TRANSPORTMULTITHTTP_17_054: [Request HTTP headers shall have the value of "Content-Type" created or updated to "application/vnd.microsoft.iothub.json" by a call to HTTPHeaders_ReplaceHeaderNameValuePair.] */
XinZhangMS 0:f7f1f0d76dd6 1366 if (HTTPHeaders_ReplaceHeaderNameValuePair(deviceData->eventHTTPrequestHeaders, CONTENT_TYPE, APPLICATION_VND_MICROSOFT_IOTHUB_JSON) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1367 {
XinZhangMS 0:f7f1f0d76dd6 1368 /*Codes_SRS_TRANSPORTMULTITHTTP_17_055: [If updating Content-Type fails for any reason, then _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1369 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
XinZhangMS 0:f7f1f0d76dd6 1370 }
XinZhangMS 0:f7f1f0d76dd6 1371 else
XinZhangMS 0:f7f1f0d76dd6 1372 {
XinZhangMS 0:f7f1f0d76dd6 1373 /*Codes_SRS_TRANSPORTMULTITHTTP_17_059: [It shall inspect the "waitingToSend" DLIST passed in config structure.] */
XinZhangMS 0:f7f1f0d76dd6 1374 STRING_HANDLE payload;
XinZhangMS 0:f7f1f0d76dd6 1375 switch (makePayload(deviceData, &payload))
XinZhangMS 0:f7f1f0d76dd6 1376 {
XinZhangMS 0:f7f1f0d76dd6 1377 case MAKE_PAYLOAD_OK:
XinZhangMS 0:f7f1f0d76dd6 1378 {
XinZhangMS 0:f7f1f0d76dd6 1379 /*Codes_SRS_TRANSPORTMULTITHTTP_17_068: [Once a final payload has been obtained, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters:] */
XinZhangMS 0:f7f1f0d76dd6 1380 BUFFER_HANDLE temp = BUFFER_new();
XinZhangMS 0:f7f1f0d76dd6 1381 if (temp == NULL)
XinZhangMS 0:f7f1f0d76dd6 1382 {
XinZhangMS 0:f7f1f0d76dd6 1383 LogError("unable to BUFFER_new");
XinZhangMS 0:f7f1f0d76dd6 1384 /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
XinZhangMS 0:f7f1f0d76dd6 1385 reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
XinZhangMS 0:f7f1f0d76dd6 1386 }
XinZhangMS 0:f7f1f0d76dd6 1387 else
XinZhangMS 0:f7f1f0d76dd6 1388 {
XinZhangMS 0:f7f1f0d76dd6 1389 if (BUFFER_build(temp, (const unsigned char*)STRING_c_str(payload), STRING_length(payload)) != 0)
XinZhangMS 0:f7f1f0d76dd6 1390 {
XinZhangMS 0:f7f1f0d76dd6 1391 LogError("unable to BUFFER_build");
XinZhangMS 0:f7f1f0d76dd6 1392 //items go back to waitingToSend
XinZhangMS 0:f7f1f0d76dd6 1393 /*Codes_SRS_TRANSPORTMULTITHTTP_17_067: [If there is no valid payload, IoTHubTransportHttp_DoWork shall advance to the next activity.]*/
XinZhangMS 0:f7f1f0d76dd6 1394 reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
XinZhangMS 0:f7f1f0d76dd6 1395 }
XinZhangMS 0:f7f1f0d76dd6 1396 else
XinZhangMS 0:f7f1f0d76dd6 1397 {
XinZhangMS 0:f7f1f0d76dd6 1398 unsigned int statusCode;
XinZhangMS 0:f7f1f0d76dd6 1399 if (HTTPAPIEX_SAS_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 1400 deviceData->sasObject,
XinZhangMS 0:f7f1f0d76dd6 1401 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 1402 HTTPAPI_REQUEST_POST,
XinZhangMS 0:f7f1f0d76dd6 1403 STRING_c_str(deviceData->eventHTTPrelativePath),
XinZhangMS 0:f7f1f0d76dd6 1404 deviceData->eventHTTPrequestHeaders,
XinZhangMS 0:f7f1f0d76dd6 1405 temp,
XinZhangMS 0:f7f1f0d76dd6 1406 &statusCode,
XinZhangMS 0:f7f1f0d76dd6 1407 NULL,
XinZhangMS 0:f7f1f0d76dd6 1408 NULL
XinZhangMS 0:f7f1f0d76dd6 1409 ) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1410 {
XinZhangMS 0:f7f1f0d76dd6 1411 LogError("unable to HTTPAPIEX_ExecuteRequest");
XinZhangMS 0:f7f1f0d76dd6 1412 //items go back to waitingToSend
XinZhangMS 0:f7f1f0d76dd6 1413 /*Codes_SRS_TRANSPORTMULTITHTTP_17_069: [if HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
XinZhangMS 0:f7f1f0d76dd6 1414 reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
XinZhangMS 0:f7f1f0d76dd6 1415 }
XinZhangMS 0:f7f1f0d76dd6 1416 else
XinZhangMS 0:f7f1f0d76dd6 1417 {
XinZhangMS 0:f7f1f0d76dd6 1418 if (statusCode < 300)
XinZhangMS 0:f7f1f0d76dd6 1419 {
XinZhangMS 0:f7f1f0d76dd6 1420 /*Codes_SRS_TRANSPORTMULTITHTTP_17_070: [If HTTPAPIEX_SAS_ExecuteRequest does not fail and http status code <300 then IoTHubTransportHttp_DoWork shall call IoTHubClientCore_LL_SendComplete. Parameter PDLIST_ENTRY completed shall point to a list containing all the items batched, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_OK. The batched items shall be removed from waitingToSend.] */
XinZhangMS 0:f7f1f0d76dd6 1421 IoTHubClientCore_LL_SendComplete(iotHubClientHandle, &(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_OK);
XinZhangMS 0:f7f1f0d76dd6 1422 }
XinZhangMS 0:f7f1f0d76dd6 1423 else
XinZhangMS 0:f7f1f0d76dd6 1424 {
XinZhangMS 0:f7f1f0d76dd6 1425 //items go back to waitingToSend
XinZhangMS 0:f7f1f0d76dd6 1426 /*Codes_SRS_TRANSPORTMULTITHTTP_17_069: [if HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
XinZhangMS 0:f7f1f0d76dd6 1427 LogError("unexpected HTTP status code (%u)", statusCode);
XinZhangMS 0:f7f1f0d76dd6 1428 reversePutListBackIn(&(deviceData->eventConfirmations), deviceData->waitingToSend);
XinZhangMS 0:f7f1f0d76dd6 1429 }
XinZhangMS 0:f7f1f0d76dd6 1430 }
XinZhangMS 0:f7f1f0d76dd6 1431 }
XinZhangMS 0:f7f1f0d76dd6 1432 BUFFER_delete(temp);
XinZhangMS 0:f7f1f0d76dd6 1433 }
XinZhangMS 0:f7f1f0d76dd6 1434 STRING_delete(payload);
XinZhangMS 0:f7f1f0d76dd6 1435 break;
XinZhangMS 0:f7f1f0d76dd6 1436 }
XinZhangMS 0:f7f1f0d76dd6 1437 case MAKE_PAYLOAD_FIRST_ITEM_DOES_NOT_FIT:
XinZhangMS 0:f7f1f0d76dd6 1438 {
XinZhangMS 0:f7f1f0d76dd6 1439 IoTHubClientCore_LL_SendComplete(iotHubClientHandle, &(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR); /*takes care of emptying the list too*/
XinZhangMS 0:f7f1f0d76dd6 1440 break;
XinZhangMS 0:f7f1f0d76dd6 1441 }
XinZhangMS 0:f7f1f0d76dd6 1442 case MAKE_PAYLOAD_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1443 {
XinZhangMS 0:f7f1f0d76dd6 1444 LogError("unrecoverable errors while building a batch message");
XinZhangMS 0:f7f1f0d76dd6 1445 break;
XinZhangMS 0:f7f1f0d76dd6 1446 }
XinZhangMS 0:f7f1f0d76dd6 1447 case MAKE_PAYLOAD_NO_ITEMS:
XinZhangMS 0:f7f1f0d76dd6 1448 {
XinZhangMS 0:f7f1f0d76dd6 1449 /*do nothing*/
XinZhangMS 0:f7f1f0d76dd6 1450 break;
XinZhangMS 0:f7f1f0d76dd6 1451 }
XinZhangMS 0:f7f1f0d76dd6 1452 default:
XinZhangMS 0:f7f1f0d76dd6 1453 {
XinZhangMS 0:f7f1f0d76dd6 1454 LogError("internal error: switch's default branch reached when never intended");
XinZhangMS 0:f7f1f0d76dd6 1455 break;
XinZhangMS 0:f7f1f0d76dd6 1456 }
XinZhangMS 0:f7f1f0d76dd6 1457 }
XinZhangMS 0:f7f1f0d76dd6 1458 }
XinZhangMS 0:f7f1f0d76dd6 1459 }
XinZhangMS 0:f7f1f0d76dd6 1460 else
XinZhangMS 0:f7f1f0d76dd6 1461 {
XinZhangMS 0:f7f1f0d76dd6 1462 const unsigned char* messageContent = NULL;
XinZhangMS 0:f7f1f0d76dd6 1463 size_t messageSize = 0;
XinZhangMS 0:f7f1f0d76dd6 1464 size_t originalMessageSize = 0;
XinZhangMS 0:f7f1f0d76dd6 1465 IOTHUB_MESSAGE_LIST* message = containingRecord(deviceData->waitingToSend->Flink, IOTHUB_MESSAGE_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 1466 IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1467
XinZhangMS 0:f7f1f0d76dd6 1468 /*Codes_SRS_TRANSPORTMULTITHTTP_17_073: [The message size is computed from the length of the payload + 384.]*/
XinZhangMS 0:f7f1f0d76dd6 1469 if (!(
XinZhangMS 0:f7f1f0d76dd6 1470 (((contentType == IOTHUBMESSAGE_BYTEARRAY) &&
XinZhangMS 0:f7f1f0d76dd6 1471 (IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &originalMessageSize) == IOTHUB_MESSAGE_OK))
XinZhangMS 0:f7f1f0d76dd6 1472 ? ((void)(messageSize = originalMessageSize + MAXIMUM_PAYLOAD_OVERHEAD), 1)
XinZhangMS 0:f7f1f0d76dd6 1473 : 0)
XinZhangMS 0:f7f1f0d76dd6 1474
XinZhangMS 0:f7f1f0d76dd6 1475 ||
XinZhangMS 0:f7f1f0d76dd6 1476
XinZhangMS 0:f7f1f0d76dd6 1477 ((contentType == IOTHUBMESSAGE_STRING) &&
XinZhangMS 0:f7f1f0d76dd6 1478 ((void)(messageContent = (const unsigned char*)IoTHubMessage_GetString(message->messageHandle)),
XinZhangMS 0:f7f1f0d76dd6 1479 ((void)(messageSize = MAXIMUM_PAYLOAD_OVERHEAD + (originalMessageSize = ((messageContent == NULL)
XinZhangMS 0:f7f1f0d76dd6 1480 ? 0
XinZhangMS 0:f7f1f0d76dd6 1481 : strlen((const char*)messageContent))))),
XinZhangMS 0:f7f1f0d76dd6 1482 messageContent != NULL)
XinZhangMS 0:f7f1f0d76dd6 1483 )
XinZhangMS 0:f7f1f0d76dd6 1484 ))
XinZhangMS 0:f7f1f0d76dd6 1485 {
XinZhangMS 0:f7f1f0d76dd6 1486 LogError("unable to get the message content");
XinZhangMS 0:f7f1f0d76dd6 1487 /*go on...*/
XinZhangMS 0:f7f1f0d76dd6 1488 }
XinZhangMS 0:f7f1f0d76dd6 1489 else
XinZhangMS 0:f7f1f0d76dd6 1490 {
XinZhangMS 0:f7f1f0d76dd6 1491 /*Codes_SRS_TRANSPORTMULTITHTTP_17_075: [If the oldest message in waitingToSend causes the message to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClientCore_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_BATCHSTATE_FAILED.]*/
XinZhangMS 0:f7f1f0d76dd6 1492 /*Codes_SRS_TRANSPORTMULTITHTTP_17_072: [The message size shall be limited to 255KB -1 bytes.] */
XinZhangMS 0:f7f1f0d76dd6 1493 if (messageSize > MAXIMUM_MESSAGE_SIZE)
XinZhangMS 0:f7f1f0d76dd6 1494 {
XinZhangMS 0:f7f1f0d76dd6 1495 PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1496 DList_InsertTailList(&(deviceData->eventConfirmations), head);
XinZhangMS 0:f7f1f0d76dd6 1497 IoTHubClientCore_LL_SendComplete(iotHubClientHandle, &(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR); /*takes care of emptying the list too*/
XinZhangMS 0:f7f1f0d76dd6 1498 }
XinZhangMS 0:f7f1f0d76dd6 1499 else
XinZhangMS 0:f7f1f0d76dd6 1500 {
XinZhangMS 0:f7f1f0d76dd6 1501 /*Codes_SRS_TRANSPORTMULTITHTTP_17_071: [If option SetBatching is false then _Dowork shall send individual event message as specced below.] */
XinZhangMS 0:f7f1f0d76dd6 1502 /*Codes_SRS_TRANSPORTMULTITHTTP_17_076: [A clone of the event HTTP request headers shall be created.]*/
XinZhangMS 0:f7f1f0d76dd6 1503 HTTP_HEADERS_HANDLE clonedEventHTTPrequestHeaders = HTTPHeaders_Clone(deviceData->eventHTTPrequestHeaders);
XinZhangMS 0:f7f1f0d76dd6 1504 if (clonedEventHTTPrequestHeaders == NULL)
XinZhangMS 0:f7f1f0d76dd6 1505 {
XinZhangMS 0:f7f1f0d76dd6 1506 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1507 LogError("HTTPHeaders_Clone failed");
XinZhangMS 0:f7f1f0d76dd6 1508 }
XinZhangMS 0:f7f1f0d76dd6 1509 else
XinZhangMS 0:f7f1f0d76dd6 1510 {
XinZhangMS 0:f7f1f0d76dd6 1511 /*Codes_SRS_TRANSPORTMULTITHTTP_17_077: [The cloned HTTP headers shall have the HTTP header "Content-Type" set to "application/octet-stream".] */
XinZhangMS 0:f7f1f0d76dd6 1512 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, CONTENT_TYPE, APPLICATION_OCTET_STREAM) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1513 {
XinZhangMS 0:f7f1f0d76dd6 1514 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1515 LogError("HTTPHeaders_ReplaceHeaderNameValuePair failed");
XinZhangMS 0:f7f1f0d76dd6 1516 }
XinZhangMS 0:f7f1f0d76dd6 1517 else
XinZhangMS 0:f7f1f0d76dd6 1518 {
XinZhangMS 0:f7f1f0d76dd6 1519 /*Codes_SRS_TRANSPORTMULTITHTTP_17_078: [Every message property "property":"value" shall be added to the HTTP headers as an individual header "iothub-app-property":"value".] */
XinZhangMS 0:f7f1f0d76dd6 1520 MAP_HANDLE map = IoTHubMessage_Properties(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1521 const char*const* keys;
XinZhangMS 0:f7f1f0d76dd6 1522 const char*const* values;
XinZhangMS 0:f7f1f0d76dd6 1523 size_t count;
XinZhangMS 0:f7f1f0d76dd6 1524 if (Map_GetInternals(map, &keys, &values, &count) != MAP_OK)
XinZhangMS 0:f7f1f0d76dd6 1525 {
XinZhangMS 0:f7f1f0d76dd6 1526 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1527 LogError("unable to Map_GetInternals");
XinZhangMS 0:f7f1f0d76dd6 1528 }
XinZhangMS 0:f7f1f0d76dd6 1529 else
XinZhangMS 0:f7f1f0d76dd6 1530 {
XinZhangMS 0:f7f1f0d76dd6 1531 size_t i;
XinZhangMS 0:f7f1f0d76dd6 1532 bool goOn = true;
XinZhangMS 0:f7f1f0d76dd6 1533 const char* msgId;
XinZhangMS 0:f7f1f0d76dd6 1534 const char* corrId;
XinZhangMS 0:f7f1f0d76dd6 1535 const char* userDefinedContentType;
XinZhangMS 0:f7f1f0d76dd6 1536 const char* contentEncoding;
XinZhangMS 0:f7f1f0d76dd6 1537
XinZhangMS 0:f7f1f0d76dd6 1538 for (i = 0; (i < count) && goOn; i++)
XinZhangMS 0:f7f1f0d76dd6 1539 {
XinZhangMS 0:f7f1f0d76dd6 1540 /*Codes_SRS_TRANSPORTMULTITHTTP_17_074: [Every property name shall add to the message size the length of the property name + the length of the property value + 16 bytes.] */
XinZhangMS 0:f7f1f0d76dd6 1541 messageSize += (strlen(values[i]) + strlen(keys[i]) + MAXIMUM_PROPERTY_OVERHEAD);
XinZhangMS 0:f7f1f0d76dd6 1542 if (messageSize > MAXIMUM_MESSAGE_SIZE)
XinZhangMS 0:f7f1f0d76dd6 1543 {
XinZhangMS 0:f7f1f0d76dd6 1544 /*Codes_SRS_TRANSPORTMULTITHTTP_17_072: [The message size shall be limited to 255KB -1 bytes.] */
XinZhangMS 0:f7f1f0d76dd6 1545 PDLIST_ENTRY head = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1546 DList_InsertTailList(&(deviceData->eventConfirmations), head);
XinZhangMS 0:f7f1f0d76dd6 1547 IoTHubClientCore_LL_SendComplete(iotHubClientHandle, &(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_ERROR); /*takes care of emptying the list too*/
XinZhangMS 0:f7f1f0d76dd6 1548 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1549 }
XinZhangMS 0:f7f1f0d76dd6 1550 else
XinZhangMS 0:f7f1f0d76dd6 1551 {
XinZhangMS 0:f7f1f0d76dd6 1552 STRING_HANDLE temp = STRING_construct(IOTHUB_APP_PREFIX);
XinZhangMS 0:f7f1f0d76dd6 1553 if (temp == NULL)
XinZhangMS 0:f7f1f0d76dd6 1554 {
XinZhangMS 0:f7f1f0d76dd6 1555 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1556 LogError("unable to STRING_construct");
XinZhangMS 0:f7f1f0d76dd6 1557 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1558 }
XinZhangMS 0:f7f1f0d76dd6 1559 else
XinZhangMS 0:f7f1f0d76dd6 1560 {
XinZhangMS 0:f7f1f0d76dd6 1561 if (STRING_concat(temp, keys[i]) != 0)
XinZhangMS 0:f7f1f0d76dd6 1562 {
XinZhangMS 0:f7f1f0d76dd6 1563 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1564 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1565 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1566 }
XinZhangMS 0:f7f1f0d76dd6 1567 else
XinZhangMS 0:f7f1f0d76dd6 1568 {
XinZhangMS 0:f7f1f0d76dd6 1569 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, STRING_c_str(temp), values[i]) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1570 {
XinZhangMS 0:f7f1f0d76dd6 1571 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1572 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
XinZhangMS 0:f7f1f0d76dd6 1573 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1574 }
XinZhangMS 0:f7f1f0d76dd6 1575 }
XinZhangMS 0:f7f1f0d76dd6 1576 STRING_delete(temp);
XinZhangMS 0:f7f1f0d76dd6 1577 }
XinZhangMS 0:f7f1f0d76dd6 1578 }
XinZhangMS 0:f7f1f0d76dd6 1579 }
XinZhangMS 0:f7f1f0d76dd6 1580
XinZhangMS 0:f7f1f0d76dd6 1581 // Add the Message Id and the Correlation Id
XinZhangMS 0:f7f1f0d76dd6 1582 msgId = IoTHubMessage_GetMessageId(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1583 if (goOn && msgId != NULL)
XinZhangMS 0:f7f1f0d76dd6 1584 {
XinZhangMS 0:f7f1f0d76dd6 1585 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, IOTHUB_MESSAGE_ID, msgId) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1586 {
XinZhangMS 0:f7f1f0d76dd6 1587 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
XinZhangMS 0:f7f1f0d76dd6 1588 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1589 }
XinZhangMS 0:f7f1f0d76dd6 1590 }
XinZhangMS 0:f7f1f0d76dd6 1591
XinZhangMS 0:f7f1f0d76dd6 1592 corrId = IoTHubMessage_GetCorrelationId(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1593 if (goOn && corrId != NULL)
XinZhangMS 0:f7f1f0d76dd6 1594 {
XinZhangMS 0:f7f1f0d76dd6 1595 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, IOTHUB_CORRELATION_ID, corrId) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1596 {
XinZhangMS 0:f7f1f0d76dd6 1597 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair");
XinZhangMS 0:f7f1f0d76dd6 1598 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1599 }
XinZhangMS 0:f7f1f0d76dd6 1600 }
XinZhangMS 0:f7f1f0d76dd6 1601
XinZhangMS 0:f7f1f0d76dd6 1602 // Codes_SRS_TRANSPORTMULTITHTTP_09_001: [ If the IoTHubMessage being sent contains property `content-type` it shall be added to the HTTP headers as "iothub-contenttype":"value". ]
XinZhangMS 0:f7f1f0d76dd6 1603 userDefinedContentType = IoTHubMessage_GetContentTypeSystemProperty(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1604 if (goOn && userDefinedContentType != NULL)
XinZhangMS 0:f7f1f0d76dd6 1605 {
XinZhangMS 0:f7f1f0d76dd6 1606 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, IOTHUB_CONTENT_TYPE_D2C, userDefinedContentType) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1607 {
XinZhangMS 0:f7f1f0d76dd6 1608 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair (content-type)");
XinZhangMS 0:f7f1f0d76dd6 1609 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1610 }
XinZhangMS 0:f7f1f0d76dd6 1611 }
XinZhangMS 0:f7f1f0d76dd6 1612
XinZhangMS 0:f7f1f0d76dd6 1613 // Codes_SRS_TRANSPORTMULTITHTTP_09_002: [ If the IoTHubMessage being sent contains property `content-encoding` it shall be added to the HTTP headers as "iothub-contentencoding":"value". ]
XinZhangMS 0:f7f1f0d76dd6 1614 contentEncoding = IoTHubMessage_GetContentEncodingSystemProperty(message->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1615 if (goOn && contentEncoding != NULL)
XinZhangMS 0:f7f1f0d76dd6 1616 {
XinZhangMS 0:f7f1f0d76dd6 1617 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, IOTHUB_CONTENT_ENCODING_D2C, contentEncoding) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1618 {
XinZhangMS 0:f7f1f0d76dd6 1619 LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair (content-encoding)");
XinZhangMS 0:f7f1f0d76dd6 1620 goOn = false;
XinZhangMS 0:f7f1f0d76dd6 1621 }
XinZhangMS 0:f7f1f0d76dd6 1622 }
XinZhangMS 0:f7f1f0d76dd6 1623
XinZhangMS 0:f7f1f0d76dd6 1624 if (!goOn)
XinZhangMS 0:f7f1f0d76dd6 1625 {
XinZhangMS 0:f7f1f0d76dd6 1626 /*Codes_SRS_TRANSPORTMULTITHTTP_17_079: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 1627 }
XinZhangMS 0:f7f1f0d76dd6 1628 else
XinZhangMS 0:f7f1f0d76dd6 1629 {
XinZhangMS 0:f7f1f0d76dd6 1630 BUFFER_HANDLE toBeSend = BUFFER_new();
XinZhangMS 0:f7f1f0d76dd6 1631 if (toBeSend == NULL)
XinZhangMS 0:f7f1f0d76dd6 1632 {
XinZhangMS 0:f7f1f0d76dd6 1633 LogError("unable to BUFFER_new");
XinZhangMS 0:f7f1f0d76dd6 1634 }
XinZhangMS 0:f7f1f0d76dd6 1635 else
XinZhangMS 0:f7f1f0d76dd6 1636 {
XinZhangMS 0:f7f1f0d76dd6 1637 if (BUFFER_build(toBeSend, messageContent, originalMessageSize) != 0)
XinZhangMS 0:f7f1f0d76dd6 1638 {
XinZhangMS 0:f7f1f0d76dd6 1639 LogError("unable to BUFFER_build");
XinZhangMS 0:f7f1f0d76dd6 1640 }
XinZhangMS 0:f7f1f0d76dd6 1641 else
XinZhangMS 0:f7f1f0d76dd6 1642 {
XinZhangMS 0:f7f1f0d76dd6 1643 unsigned int statusCode = 0;
XinZhangMS 0:f7f1f0d76dd6 1644 HTTPAPIEX_RESULT r;
XinZhangMS 0:f7f1f0d76dd6 1645 if (deviceData->deviceSasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 1646 {
XinZhangMS 0:f7f1f0d76dd6 1647 /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
XinZhangMS 0:f7f1f0d76dd6 1648 if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, "Authorization", STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1649 {
XinZhangMS 0:f7f1f0d76dd6 1650 r = HTTPAPIEX_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1651 /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
XinZhangMS 0:f7f1f0d76dd6 1652 LogError("Unable to replace the old SAS Token.");
XinZhangMS 0:f7f1f0d76dd6 1653 }
XinZhangMS 0:f7f1f0d76dd6 1654
XinZhangMS 0:f7f1f0d76dd6 1655 /*Codes_SRS_TRANSPORTMULTITHTTP_03_003: [If a deviceSasToken exists, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_ExecuteRequest passing the following parameters] */
XinZhangMS 0:f7f1f0d76dd6 1656 else if ((r = HTTPAPIEX_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 1657 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 1658 HTTPAPI_REQUEST_POST,
XinZhangMS 0:f7f1f0d76dd6 1659 STRING_c_str(deviceData->eventHTTPrelativePath),
XinZhangMS 0:f7f1f0d76dd6 1660 clonedEventHTTPrequestHeaders,
XinZhangMS 0:f7f1f0d76dd6 1661 toBeSend,
XinZhangMS 0:f7f1f0d76dd6 1662 &statusCode,
XinZhangMS 0:f7f1f0d76dd6 1663 NULL,
XinZhangMS 0:f7f1f0d76dd6 1664 NULL
XinZhangMS 0:f7f1f0d76dd6 1665 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1666 {
XinZhangMS 0:f7f1f0d76dd6 1667 LogError("Unable to HTTPAPIEX_ExecuteRequest.");
XinZhangMS 0:f7f1f0d76dd6 1668 }
XinZhangMS 0:f7f1f0d76dd6 1669 }
XinZhangMS 0:f7f1f0d76dd6 1670 else
XinZhangMS 0:f7f1f0d76dd6 1671 {
XinZhangMS 0:f7f1f0d76dd6 1672 /*Codes_SRS_TRANSPORTMULTITHTTP_17_080: [If a deviceSasToken does not exist, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters] */
XinZhangMS 0:f7f1f0d76dd6 1673 if ((r = HTTPAPIEX_SAS_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 1674 deviceData->sasObject,
XinZhangMS 0:f7f1f0d76dd6 1675 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 1676 HTTPAPI_REQUEST_POST,
XinZhangMS 0:f7f1f0d76dd6 1677 STRING_c_str(deviceData->eventHTTPrelativePath),
XinZhangMS 0:f7f1f0d76dd6 1678 clonedEventHTTPrequestHeaders,
XinZhangMS 0:f7f1f0d76dd6 1679 toBeSend,
XinZhangMS 0:f7f1f0d76dd6 1680 &statusCode,
XinZhangMS 0:f7f1f0d76dd6 1681 NULL,
XinZhangMS 0:f7f1f0d76dd6 1682 NULL
XinZhangMS 0:f7f1f0d76dd6 1683 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1684 {
XinZhangMS 0:f7f1f0d76dd6 1685 LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
XinZhangMS 0:f7f1f0d76dd6 1686 }
XinZhangMS 0:f7f1f0d76dd6 1687 }
XinZhangMS 0:f7f1f0d76dd6 1688 if (r == HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1689 {
XinZhangMS 0:f7f1f0d76dd6 1690 if (statusCode < 300)
XinZhangMS 0:f7f1f0d76dd6 1691 {
XinZhangMS 0:f7f1f0d76dd6 1692 /*Codes_SRS_TRANSPORTMULTITHTTP_17_082: [If HTTPAPIEX_SAS_ExecuteRequest does not fail and http status code <300 then IoTHubTransportHttp_DoWork shall call IoTHubClientCore_LL_SendComplete. Parameter PDLIST_ENTRY completed shall point to a list the item send, and parameter IOTHUB_CLIENT_CONFIRMATION_RESULT result shall be set to IOTHUB_CLIENT_CONFIRMATION_OK. The item shall be removed from waitingToSend.] */
XinZhangMS 0:f7f1f0d76dd6 1693 PDLIST_ENTRY justSent = DList_RemoveHeadList(deviceData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
XinZhangMS 0:f7f1f0d76dd6 1694 DList_InsertTailList(&(deviceData->eventConfirmations), justSent);
XinZhangMS 0:f7f1f0d76dd6 1695 IoTHubClientCore_LL_SendComplete(iotHubClientHandle, &(deviceData->eventConfirmations), IOTHUB_CLIENT_CONFIRMATION_OK); /*takes care of emptying the list too*/
XinZhangMS 0:f7f1f0d76dd6 1696 }
XinZhangMS 0:f7f1f0d76dd6 1697 else
XinZhangMS 0:f7f1f0d76dd6 1698 {
XinZhangMS 0:f7f1f0d76dd6 1699 /*Codes_SRS_TRANSPORTMULTITHTTP_17_081: [If HTTPAPIEX_SAS_ExecuteRequest fails or the http status code >=300 then IoTHubTransportHttp_DoWork shall not do any other action (it is assumed at the next _DoWork it shall be retried).] */
XinZhangMS 0:f7f1f0d76dd6 1700 LogError("unexpected HTTP status code (%u)", statusCode);
XinZhangMS 0:f7f1f0d76dd6 1701 }
XinZhangMS 0:f7f1f0d76dd6 1702 }
XinZhangMS 0:f7f1f0d76dd6 1703 }
XinZhangMS 0:f7f1f0d76dd6 1704 BUFFER_delete(toBeSend);
XinZhangMS 0:f7f1f0d76dd6 1705 }
XinZhangMS 0:f7f1f0d76dd6 1706 }
XinZhangMS 0:f7f1f0d76dd6 1707 }
XinZhangMS 0:f7f1f0d76dd6 1708 }
XinZhangMS 0:f7f1f0d76dd6 1709 HTTPHeaders_Free(clonedEventHTTPrequestHeaders);
XinZhangMS 0:f7f1f0d76dd6 1710 }
XinZhangMS 0:f7f1f0d76dd6 1711 }
XinZhangMS 0:f7f1f0d76dd6 1712 }
XinZhangMS 0:f7f1f0d76dd6 1713 }
XinZhangMS 0:f7f1f0d76dd6 1714 }
XinZhangMS 0:f7f1f0d76dd6 1715 }
XinZhangMS 0:f7f1f0d76dd6 1716
XinZhangMS 0:f7f1f0d76dd6 1717 static bool abandonOrAcceptMessage(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, const char* ETag, IOTHUBMESSAGE_DISPOSITION_RESULT action)
XinZhangMS 0:f7f1f0d76dd6 1718 {
XinZhangMS 0:f7f1f0d76dd6 1719 /*Codes_SRS_TRANSPORTMULTITHTTP_17_097: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
XinZhangMS 0:f7f1f0d76dd6 1720 -requestType: POST
XinZhangMS 0:f7f1f0d76dd6 1721 -relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14"
XinZhangMS 0:f7f1f0d76dd6 1722 - requestHttpHeadersHandle: an HTTP headers instance containing the following
XinZhangMS 0:f7f1f0d76dd6 1723 Authorization: " "
XinZhangMS 0:f7f1f0d76dd6 1724 If-Match: value of ETag
XinZhangMS 0:f7f1f0d76dd6 1725 - requestContent: NULL
XinZhangMS 0:f7f1f0d76dd6 1726 - statusCode: a pointer to unsigned int which might be examined for logging
XinZhangMS 0:f7f1f0d76dd6 1727 - responseHeadearsHandle: NULL
XinZhangMS 0:f7f1f0d76dd6 1728 - responseContent: NULL]*/
XinZhangMS 0:f7f1f0d76dd6 1729 /*Codes_SRS_TRANSPORTMULTITHTTP_17_099: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
XinZhangMS 0:f7f1f0d76dd6 1730 -requestType: DELETE
XinZhangMS 0:f7f1f0d76dd6 1731 -relativePath: abandon relative path begin + value of ETag + "?api-version=2016-11-14"
XinZhangMS 0:f7f1f0d76dd6 1732 - requestHttpHeadersHandle: an HTTP headers instance containing the following
XinZhangMS 0:f7f1f0d76dd6 1733 Authorization: " "
XinZhangMS 0:f7f1f0d76dd6 1734 If-Match: value of ETag
XinZhangMS 0:f7f1f0d76dd6 1735 - requestContent: NULL
XinZhangMS 0:f7f1f0d76dd6 1736 - statusCode: a pointer to unsigned int which might be used by logging
XinZhangMS 0:f7f1f0d76dd6 1737 - responseHeadearsHandle: NULL
XinZhangMS 0:f7f1f0d76dd6 1738 - responseContent: NULL]*/
XinZhangMS 0:f7f1f0d76dd6 1739 /*Codes_SRS_TRANSPORTMULTITHTTP_17_101: [_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest with the following parameters:
XinZhangMS 0:f7f1f0d76dd6 1740 -requestType: DELETE
XinZhangMS 0:f7f1f0d76dd6 1741 -relativePath: abandon relative path begin + value of ETag +"?api-version=2016-11-14" + "&reject"
XinZhangMS 0:f7f1f0d76dd6 1742 - requestHttpHeadersHandle: an HTTP headers instance containing the following
XinZhangMS 0:f7f1f0d76dd6 1743 Authorization: " "
XinZhangMS 0:f7f1f0d76dd6 1744 If-Match: value of ETag
XinZhangMS 0:f7f1f0d76dd6 1745 - requestContent: NULL
XinZhangMS 0:f7f1f0d76dd6 1746 - statusCode: a pointer to unsigned int which might be used by logging
XinZhangMS 0:f7f1f0d76dd6 1747 - responseHeadearsHandle: NULL
XinZhangMS 0:f7f1f0d76dd6 1748 - responseContent: NULL]*/
XinZhangMS 0:f7f1f0d76dd6 1749
XinZhangMS 0:f7f1f0d76dd6 1750 bool result;
XinZhangMS 0:f7f1f0d76dd6 1751 STRING_HANDLE fullAbandonRelativePath = STRING_clone(deviceData->abandonHTTPrelativePathBegin);
XinZhangMS 0:f7f1f0d76dd6 1752 if (fullAbandonRelativePath == NULL)
XinZhangMS 0:f7f1f0d76dd6 1753 {
XinZhangMS 0:f7f1f0d76dd6 1754 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1755 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1756 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1757 LogError("unable to STRING_clone");
XinZhangMS 0:f7f1f0d76dd6 1758 result = false;
XinZhangMS 0:f7f1f0d76dd6 1759 }
XinZhangMS 0:f7f1f0d76dd6 1760 else
XinZhangMS 0:f7f1f0d76dd6 1761 {
XinZhangMS 0:f7f1f0d76dd6 1762 STRING_HANDLE ETagUnquoted = STRING_construct_n(ETag + 1, strlen(ETag) - 2); /*skip first character which is '"' and the last one (which is also '"')*/
XinZhangMS 0:f7f1f0d76dd6 1763 if (ETagUnquoted == NULL)
XinZhangMS 0:f7f1f0d76dd6 1764 {
XinZhangMS 0:f7f1f0d76dd6 1765 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1766 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1767 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1768 LogError("unable to STRING_construct_n");
XinZhangMS 0:f7f1f0d76dd6 1769 result = false;
XinZhangMS 0:f7f1f0d76dd6 1770 }
XinZhangMS 0:f7f1f0d76dd6 1771 else
XinZhangMS 0:f7f1f0d76dd6 1772 {
XinZhangMS 0:f7f1f0d76dd6 1773 if (!(
XinZhangMS 0:f7f1f0d76dd6 1774 (STRING_concat_with_STRING(fullAbandonRelativePath, ETagUnquoted) == 0) &&
XinZhangMS 0:f7f1f0d76dd6 1775 (STRING_concat(fullAbandonRelativePath, (action == IOTHUBMESSAGE_ABANDONED) ? "/abandon" API_VERSION : ((action == IOTHUBMESSAGE_REJECTED) ? API_VERSION "&reject" : API_VERSION)) == 0)
XinZhangMS 0:f7f1f0d76dd6 1776 ))
XinZhangMS 0:f7f1f0d76dd6 1777 {
XinZhangMS 0:f7f1f0d76dd6 1778 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1779 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1780 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1781 LogError("unable to STRING_concat");
XinZhangMS 0:f7f1f0d76dd6 1782 result = false;
XinZhangMS 0:f7f1f0d76dd6 1783 }
XinZhangMS 0:f7f1f0d76dd6 1784 else
XinZhangMS 0:f7f1f0d76dd6 1785 {
XinZhangMS 0:f7f1f0d76dd6 1786 HTTP_HEADERS_HANDLE abandonRequestHttpHeaders = HTTPHeaders_Alloc();
XinZhangMS 0:f7f1f0d76dd6 1787 if (abandonRequestHttpHeaders == NULL)
XinZhangMS 0:f7f1f0d76dd6 1788 {
XinZhangMS 0:f7f1f0d76dd6 1789 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1790 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1791 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1792 LogError("unable to HTTPHeaders_Alloc");
XinZhangMS 0:f7f1f0d76dd6 1793 result = false;
XinZhangMS 0:f7f1f0d76dd6 1794 }
XinZhangMS 0:f7f1f0d76dd6 1795 else
XinZhangMS 0:f7f1f0d76dd6 1796 {
XinZhangMS 0:f7f1f0d76dd6 1797 if (!(
XinZhangMS 0:f7f1f0d76dd6 1798 (addUserAgentHeaderInfo(deviceData->iotHubClientHandle, abandonRequestHttpHeaders) == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 1799 (HTTPHeaders_AddHeaderNameValuePair(abandonRequestHttpHeaders, "Authorization", " ") == HTTP_HEADERS_OK) &&
XinZhangMS 0:f7f1f0d76dd6 1800 (HTTPHeaders_AddHeaderNameValuePair(abandonRequestHttpHeaders, "If-Match", ETag) == HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1801 ))
XinZhangMS 0:f7f1f0d76dd6 1802 {
XinZhangMS 0:f7f1f0d76dd6 1803 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1804 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1805 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1806 LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
XinZhangMS 0:f7f1f0d76dd6 1807 result = false;
XinZhangMS 0:f7f1f0d76dd6 1808 }
XinZhangMS 0:f7f1f0d76dd6 1809 else
XinZhangMS 0:f7f1f0d76dd6 1810 {
XinZhangMS 0:f7f1f0d76dd6 1811 unsigned int statusCode = 0;
XinZhangMS 0:f7f1f0d76dd6 1812 HTTPAPIEX_RESULT r;
XinZhangMS 0:f7f1f0d76dd6 1813 if (deviceData->deviceSasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 1814 {
XinZhangMS 0:f7f1f0d76dd6 1815 /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
XinZhangMS 0:f7f1f0d76dd6 1816 if (HTTPHeaders_ReplaceHeaderNameValuePair(abandonRequestHttpHeaders, "Authorization", STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 1817 {
XinZhangMS 0:f7f1f0d76dd6 1818 r = HTTPAPIEX_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1819 /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
XinZhangMS 0:f7f1f0d76dd6 1820 LogError("Unable to replace the old SAS Token.");
XinZhangMS 0:f7f1f0d76dd6 1821 result = false;
XinZhangMS 0:f7f1f0d76dd6 1822 }
XinZhangMS 0:f7f1f0d76dd6 1823 else if ((r = HTTPAPIEX_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 1824 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 1825 (action == IOTHUBMESSAGE_ABANDONED) ? HTTPAPI_REQUEST_POST : HTTPAPI_REQUEST_DELETE, /*-requestType: POST */
XinZhangMS 0:f7f1f0d76dd6 1826 STRING_c_str(fullAbandonRelativePath), /*-relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14" */
XinZhangMS 0:f7f1f0d76dd6 1827 abandonRequestHttpHeaders, /*- requestHttpHeadersHandle: an HTTP headers instance containing the following */
XinZhangMS 0:f7f1f0d76dd6 1828 NULL, /*- requestContent: NULL */
XinZhangMS 0:f7f1f0d76dd6 1829 &statusCode, /*- statusCode: a pointer to unsigned int which might be examined for logging */
XinZhangMS 0:f7f1f0d76dd6 1830 NULL, /*- responseHeadearsHandle: NULL */
XinZhangMS 0:f7f1f0d76dd6 1831 NULL /*- responseContent: NULL] */
XinZhangMS 0:f7f1f0d76dd6 1832 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1833 {
XinZhangMS 0:f7f1f0d76dd6 1834 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1835 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1836 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1837 LogError("Unable to HTTPAPIEX_ExecuteRequest.");
XinZhangMS 0:f7f1f0d76dd6 1838 result = false;
XinZhangMS 0:f7f1f0d76dd6 1839 }
XinZhangMS 0:f7f1f0d76dd6 1840 }
XinZhangMS 0:f7f1f0d76dd6 1841 else if ((r = HTTPAPIEX_SAS_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 1842 deviceData->sasObject,
XinZhangMS 0:f7f1f0d76dd6 1843 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 1844 (action == IOTHUBMESSAGE_ABANDONED) ? HTTPAPI_REQUEST_POST : HTTPAPI_REQUEST_DELETE, /*-requestType: POST */
XinZhangMS 0:f7f1f0d76dd6 1845 STRING_c_str(fullAbandonRelativePath), /*-relativePath: abandon relative path begin (as created by _Create) + value of ETag + "/abandon?api-version=2016-11-14" */
XinZhangMS 0:f7f1f0d76dd6 1846 abandonRequestHttpHeaders, /*- requestHttpHeadersHandle: an HTTP headers instance containing the following */
XinZhangMS 0:f7f1f0d76dd6 1847 NULL, /*- requestContent: NULL */
XinZhangMS 0:f7f1f0d76dd6 1848 &statusCode, /*- statusCode: a pointer to unsigned int which might be examined for logging */
XinZhangMS 0:f7f1f0d76dd6 1849 NULL, /*- responseHeadearsHandle: NULL */
XinZhangMS 0:f7f1f0d76dd6 1850 NULL /*- responseContent: NULL] */
XinZhangMS 0:f7f1f0d76dd6 1851 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1852 {
XinZhangMS 0:f7f1f0d76dd6 1853 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1854 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1855 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1856 LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
XinZhangMS 0:f7f1f0d76dd6 1857 result = false;
XinZhangMS 0:f7f1f0d76dd6 1858 }
XinZhangMS 0:f7f1f0d76dd6 1859 if (r == HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 1860 {
XinZhangMS 0:f7f1f0d76dd6 1861 if (statusCode != 204)
XinZhangMS 0:f7f1f0d76dd6 1862 {
XinZhangMS 0:f7f1f0d76dd6 1863 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1864 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1865 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1866 LogError("unexpected status code returned %u (was expecting 204)", statusCode);
XinZhangMS 0:f7f1f0d76dd6 1867 result = false;
XinZhangMS 0:f7f1f0d76dd6 1868 }
XinZhangMS 0:f7f1f0d76dd6 1869 else
XinZhangMS 0:f7f1f0d76dd6 1870 {
XinZhangMS 0:f7f1f0d76dd6 1871 /*Codes_SRS_TRANSPORTMULTITHTTP_17_098: [Abandoning the message is considered successful if the HTTPAPIEX_SAS_ExecuteRequest doesn't fail and the statusCode is 204.]*/
XinZhangMS 0:f7f1f0d76dd6 1872 /*Codes_SRS_TRANSPORTMULTITHTTP_17_100: [Accepting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1873 /*Codes_SRS_TRANSPORTMULTITHTTP_17_102: [Rejecting a message is successful when HTTPAPIEX_SAS_ExecuteRequest completes successfully and the status code is 204.] */
XinZhangMS 0:f7f1f0d76dd6 1874 /*all is fine*/
XinZhangMS 0:f7f1f0d76dd6 1875 result = true;
XinZhangMS 0:f7f1f0d76dd6 1876 }
XinZhangMS 0:f7f1f0d76dd6 1877 }
XinZhangMS 0:f7f1f0d76dd6 1878 else
XinZhangMS 0:f7f1f0d76dd6 1879 {
XinZhangMS 0:f7f1f0d76dd6 1880 result = false;
XinZhangMS 0:f7f1f0d76dd6 1881 }
XinZhangMS 0:f7f1f0d76dd6 1882 }
XinZhangMS 0:f7f1f0d76dd6 1883 HTTPHeaders_Free(abandonRequestHttpHeaders);
XinZhangMS 0:f7f1f0d76dd6 1884 }
XinZhangMS 0:f7f1f0d76dd6 1885 }
XinZhangMS 0:f7f1f0d76dd6 1886 STRING_delete(ETagUnquoted);
XinZhangMS 0:f7f1f0d76dd6 1887 }
XinZhangMS 0:f7f1f0d76dd6 1888 STRING_delete(fullAbandonRelativePath);
XinZhangMS 0:f7f1f0d76dd6 1889 }
XinZhangMS 0:f7f1f0d76dd6 1890 return result;
XinZhangMS 0:f7f1f0d76dd6 1891 }
XinZhangMS 0:f7f1f0d76dd6 1892
XinZhangMS 0:f7f1f0d76dd6 1893 static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
XinZhangMS 0:f7f1f0d76dd6 1894 {
XinZhangMS 0:f7f1f0d76dd6 1895 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 1896 if (message_data == NULL)
XinZhangMS 0:f7f1f0d76dd6 1897 {
XinZhangMS 0:f7f1f0d76dd6 1898 /* Codes_SRS_TRANSPORTMULTITHTTP_10_001: [If messageData is NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1899 LogError("invalid argument messageData is NULL");
XinZhangMS 0:f7f1f0d76dd6 1900 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1901 }
XinZhangMS 0:f7f1f0d76dd6 1902 else
XinZhangMS 0:f7f1f0d76dd6 1903 {
XinZhangMS 0:f7f1f0d76dd6 1904 if (message_data->messageHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 1905 {
XinZhangMS 0:f7f1f0d76dd6 1906 /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1907 LogError("invalid message handle");
XinZhangMS 0:f7f1f0d76dd6 1908 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1909 }
XinZhangMS 0:f7f1f0d76dd6 1910 else
XinZhangMS 0:f7f1f0d76dd6 1911 {
XinZhangMS 0:f7f1f0d76dd6 1912 MESSAGE_DISPOSITION_CONTEXT* tc = (MESSAGE_DISPOSITION_CONTEXT*)(message_data->transportContext);
XinZhangMS 0:f7f1f0d76dd6 1913 if (tc == NULL)
XinZhangMS 0:f7f1f0d76dd6 1914 {
XinZhangMS 0:f7f1f0d76dd6 1915 /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1916 LogError("invalid transport context data");
XinZhangMS 0:f7f1f0d76dd6 1917 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1918 }
XinZhangMS 0:f7f1f0d76dd6 1919 else
XinZhangMS 0:f7f1f0d76dd6 1920 {
XinZhangMS 0:f7f1f0d76dd6 1921 if ((tc->handleData == NULL) || (tc->deviceData == NULL) || (tc->etagValue == NULL))
XinZhangMS 0:f7f1f0d76dd6 1922 {
XinZhangMS 0:f7f1f0d76dd6 1923 /* Codes_SRS_TRANSPORTMULTITHTTP_10_002: [If any of the messageData fields are NULL, IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR.] */
XinZhangMS 0:f7f1f0d76dd6 1924 LogError("invalid transport context data");
XinZhangMS 0:f7f1f0d76dd6 1925 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1926 }
XinZhangMS 0:f7f1f0d76dd6 1927 else
XinZhangMS 0:f7f1f0d76dd6 1928 {
XinZhangMS 0:f7f1f0d76dd6 1929 if (abandonOrAcceptMessage(tc->handleData, tc->deviceData, tc->etagValue, disposition))
XinZhangMS 0:f7f1f0d76dd6 1930 {
XinZhangMS 0:f7f1f0d76dd6 1931 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 1932 }
XinZhangMS 0:f7f1f0d76dd6 1933 else
XinZhangMS 0:f7f1f0d76dd6 1934 {
XinZhangMS 0:f7f1f0d76dd6 1935 /* Codes_SRS_TRANSPORTMULTITHTTP_10_003: [IoTHubTransportHttp_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR if the POST message fails, otherwise return IOTHUB_CLIENT_OK.] */
XinZhangMS 0:f7f1f0d76dd6 1936 LogError("HTTP Transport layer failed to report %s disposition", ENUM_TO_STRING(IOTHUBMESSAGE_DISPOSITION_RESULT, disposition));
XinZhangMS 0:f7f1f0d76dd6 1937 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1938 }
XinZhangMS 0:f7f1f0d76dd6 1939 }
XinZhangMS 0:f7f1f0d76dd6 1940 free(tc->etagValue);
XinZhangMS 0:f7f1f0d76dd6 1941 free(tc);
XinZhangMS 0:f7f1f0d76dd6 1942 }
XinZhangMS 0:f7f1f0d76dd6 1943 IoTHubMessage_Destroy(message_data->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1944 }
XinZhangMS 0:f7f1f0d76dd6 1945 free(message_data);
XinZhangMS 0:f7f1f0d76dd6 1946 }
XinZhangMS 0:f7f1f0d76dd6 1947 return result;
XinZhangMS 0:f7f1f0d76dd6 1948 }
XinZhangMS 0:f7f1f0d76dd6 1949
XinZhangMS 0:f7f1f0d76dd6 1950 static MESSAGE_CALLBACK_INFO* MESSAGE_CALLBACK_INFO_Create(IOTHUB_MESSAGE_HANDLE received_message, HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, const char* etagValue)
XinZhangMS 0:f7f1f0d76dd6 1951 {
XinZhangMS 0:f7f1f0d76dd6 1952 MESSAGE_CALLBACK_INFO* result = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
XinZhangMS 0:f7f1f0d76dd6 1953 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 1954 {
XinZhangMS 0:f7f1f0d76dd6 1955 /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
XinZhangMS 0:f7f1f0d76dd6 1956 LogError("malloc failed");
XinZhangMS 0:f7f1f0d76dd6 1957 }
XinZhangMS 0:f7f1f0d76dd6 1958 else
XinZhangMS 0:f7f1f0d76dd6 1959 {
XinZhangMS 0:f7f1f0d76dd6 1960 MESSAGE_DISPOSITION_CONTEXT* tc = (MESSAGE_DISPOSITION_CONTEXT*)malloc(sizeof(MESSAGE_DISPOSITION_CONTEXT));
XinZhangMS 0:f7f1f0d76dd6 1961 if (tc == NULL)
XinZhangMS 0:f7f1f0d76dd6 1962 {
XinZhangMS 0:f7f1f0d76dd6 1963 /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
XinZhangMS 0:f7f1f0d76dd6 1964 LogError("malloc failed");
XinZhangMS 0:f7f1f0d76dd6 1965 free(result);
XinZhangMS 0:f7f1f0d76dd6 1966 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1967 }
XinZhangMS 0:f7f1f0d76dd6 1968 else
XinZhangMS 0:f7f1f0d76dd6 1969 {
XinZhangMS 0:f7f1f0d76dd6 1970 result->messageHandle = IoTHubMessage_Clone(received_message);
XinZhangMS 0:f7f1f0d76dd6 1971 if (result->messageHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 1972 {
XinZhangMS 0:f7f1f0d76dd6 1973 /*Codes_SRS_TRANSPORTMULTITHTTP_10_007: [If assembling a message clone, _DoWork shall "abandon" the message.]*/
XinZhangMS 0:f7f1f0d76dd6 1974 LogError("IoTHubMessage_Clone failed");
XinZhangMS 0:f7f1f0d76dd6 1975 free(tc);
XinZhangMS 0:f7f1f0d76dd6 1976 free(result);
XinZhangMS 0:f7f1f0d76dd6 1977 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1978 }
XinZhangMS 0:f7f1f0d76dd6 1979 else
XinZhangMS 0:f7f1f0d76dd6 1980 {
XinZhangMS 0:f7f1f0d76dd6 1981 if (mallocAndStrcpy_s(&tc->etagValue, etagValue) != 0)
XinZhangMS 0:f7f1f0d76dd6 1982 {
XinZhangMS 0:f7f1f0d76dd6 1983 LogError("mallocAndStrcpy_s failed");
XinZhangMS 0:f7f1f0d76dd6 1984 free(tc);
XinZhangMS 0:f7f1f0d76dd6 1985 free(result);
XinZhangMS 0:f7f1f0d76dd6 1986 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1987 }
XinZhangMS 0:f7f1f0d76dd6 1988 else
XinZhangMS 0:f7f1f0d76dd6 1989 {
XinZhangMS 0:f7f1f0d76dd6 1990 tc->handleData = handleData;
XinZhangMS 0:f7f1f0d76dd6 1991 tc->deviceData = deviceData;
XinZhangMS 0:f7f1f0d76dd6 1992
XinZhangMS 0:f7f1f0d76dd6 1993 result->transportContext = tc;
XinZhangMS 0:f7f1f0d76dd6 1994 }
XinZhangMS 0:f7f1f0d76dd6 1995 }
XinZhangMS 0:f7f1f0d76dd6 1996 }
XinZhangMS 0:f7f1f0d76dd6 1997 }
XinZhangMS 0:f7f1f0d76dd6 1998 return result;
XinZhangMS 0:f7f1f0d76dd6 1999 }
XinZhangMS 0:f7f1f0d76dd6 2000
XinZhangMS 0:f7f1f0d76dd6 2001 static void DoMessages(HTTPTRANSPORT_HANDLE_DATA* handleData, HTTPTRANSPORT_PERDEVICE_DATA* deviceData, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
XinZhangMS 0:f7f1f0d76dd6 2002 {
XinZhangMS 0:f7f1f0d76dd6 2003 /*Codes_SRS_TRANSPORTMULTITHTTP_17_083: [ If device is not subscribed then _DoWork shall advance to the next action. ] */
XinZhangMS 0:f7f1f0d76dd6 2004 if (deviceData->DoWork_PullMessage)
XinZhangMS 0:f7f1f0d76dd6 2005 {
XinZhangMS 0:f7f1f0d76dd6 2006 /*Codes_SRS_TRANSPORTMULTITHTTP_17_123: [After client creation, the first GET shall be allowed no matter what the value of GetMinimumPollingTime.] */
XinZhangMS 0:f7f1f0d76dd6 2007 /*Codes_SRS_TRANSPORTMULTITHTTP_17_124: [If time is not available then all calls shall be treated as if they are the first one.] */
XinZhangMS 0:f7f1f0d76dd6 2008 /*Codes_SRS_TRANSPORTMULTITHTTP_17_122: [A GET request that happens earlier than GetMinimumPollingTime shall be ignored.] */
XinZhangMS 0:f7f1f0d76dd6 2009 time_t timeNow = get_time(NULL);
XinZhangMS 0:f7f1f0d76dd6 2010 bool isPollingAllowed = deviceData->isFirstPoll || (timeNow == (time_t)(-1)) || (get_difftime(timeNow, deviceData->lastPollTime) > handleData->getMinimumPollingTime);
XinZhangMS 0:f7f1f0d76dd6 2011 if (isPollingAllowed)
XinZhangMS 0:f7f1f0d76dd6 2012 {
XinZhangMS 0:f7f1f0d76dd6 2013 HTTP_HEADERS_HANDLE responseHTTPHeaders = HTTPHeaders_Alloc();
XinZhangMS 0:f7f1f0d76dd6 2014 if (responseHTTPHeaders == NULL)
XinZhangMS 0:f7f1f0d76dd6 2015 {
XinZhangMS 0:f7f1f0d76dd6 2016 /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
XinZhangMS 0:f7f1f0d76dd6 2017 LogError("unable to HTTPHeaders_Alloc");
XinZhangMS 0:f7f1f0d76dd6 2018 }
XinZhangMS 0:f7f1f0d76dd6 2019 else
XinZhangMS 0:f7f1f0d76dd6 2020 {
XinZhangMS 0:f7f1f0d76dd6 2021 BUFFER_HANDLE responseContent = BUFFER_new();
XinZhangMS 0:f7f1f0d76dd6 2022 if (responseContent == NULL)
XinZhangMS 0:f7f1f0d76dd6 2023 {
XinZhangMS 0:f7f1f0d76dd6 2024 /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
XinZhangMS 0:f7f1f0d76dd6 2025 LogError("unable to BUFFER_new");
XinZhangMS 0:f7f1f0d76dd6 2026 }
XinZhangMS 0:f7f1f0d76dd6 2027 else
XinZhangMS 0:f7f1f0d76dd6 2028 {
XinZhangMS 0:f7f1f0d76dd6 2029 unsigned int statusCode = 0;
XinZhangMS 0:f7f1f0d76dd6 2030 HTTPAPIEX_RESULT r;
XinZhangMS 0:f7f1f0d76dd6 2031 if (deviceData->deviceSasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 2032 {
XinZhangMS 0:f7f1f0d76dd6 2033 /*Codes_SRS_TRANSPORTMULTITHTTP_03_001: [if a deviceSasToken exists, HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (deviceSasToken) as its third argument.]*/
XinZhangMS 0:f7f1f0d76dd6 2034 if (HTTPHeaders_ReplaceHeaderNameValuePair(deviceData->messageHTTPrequestHeaders, "Authorization", STRING_c_str(deviceData->deviceSasToken)) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 2035 {
XinZhangMS 0:f7f1f0d76dd6 2036 r = HTTPAPIEX_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2037 /*Codes_SRS_TRANSPORTMULTITHTTP_03_002: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
XinZhangMS 0:f7f1f0d76dd6 2038 LogError("Unable to replace the old SAS Token.");
XinZhangMS 0:f7f1f0d76dd6 2039 }
XinZhangMS 0:f7f1f0d76dd6 2040 else if ((r = HTTPAPIEX_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 2041 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 2042 HTTPAPI_REQUEST_GET, /*requestType: GET*/
XinZhangMS 0:f7f1f0d76dd6 2043 STRING_c_str(deviceData->messageHTTPrelativePath), /*relativePath: the message HTTP relative path*/
XinZhangMS 0:f7f1f0d76dd6 2044 deviceData->messageHTTPrequestHeaders, /*requestHttpHeadersHandle: message HTTP request headers created by _Create*/
XinZhangMS 0:f7f1f0d76dd6 2045 NULL, /*requestContent: NULL*/
XinZhangMS 0:f7f1f0d76dd6 2046 &statusCode, /*statusCode: a pointer to unsigned int which shall be later examined*/
XinZhangMS 0:f7f1f0d76dd6 2047 responseHTTPHeaders, /*responseHeadearsHandle: a new instance of HTTP headers*/
XinZhangMS 0:f7f1f0d76dd6 2048 responseContent /*responseContent: a new instance of buffer*/
XinZhangMS 0:f7f1f0d76dd6 2049 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 2050 {
XinZhangMS 0:f7f1f0d76dd6 2051 /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
XinZhangMS 0:f7f1f0d76dd6 2052 LogError("Unable to HTTPAPIEX_ExecuteRequest.");
XinZhangMS 0:f7f1f0d76dd6 2053 }
XinZhangMS 0:f7f1f0d76dd6 2054 }
XinZhangMS 0:f7f1f0d76dd6 2055
XinZhangMS 0:f7f1f0d76dd6 2056 /*Codes_SRS_TRANSPORTMULTITHTTP_17_084: [Otherwise, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters
XinZhangMS 0:f7f1f0d76dd6 2057 requestType: GET
XinZhangMS 0:f7f1f0d76dd6 2058 relativePath: the message HTTP relative path
XinZhangMS 0:f7f1f0d76dd6 2059 requestHttpHeadersHandle: message HTTP request headers created by _Create
XinZhangMS 0:f7f1f0d76dd6 2060 requestContent: NULL
XinZhangMS 0:f7f1f0d76dd6 2061 statusCode: a pointer to unsigned int which shall be later examined
XinZhangMS 0:f7f1f0d76dd6 2062 responseHeadearsHandle: a new instance of HTTP headers
XinZhangMS 0:f7f1f0d76dd6 2063 responseContent: a new instance of buffer]
XinZhangMS 0:f7f1f0d76dd6 2064 */
XinZhangMS 0:f7f1f0d76dd6 2065 else if ((r = HTTPAPIEX_SAS_ExecuteRequest(
XinZhangMS 0:f7f1f0d76dd6 2066 deviceData->sasObject,
XinZhangMS 0:f7f1f0d76dd6 2067 handleData->httpApiExHandle,
XinZhangMS 0:f7f1f0d76dd6 2068 HTTPAPI_REQUEST_GET, /*requestType: GET*/
XinZhangMS 0:f7f1f0d76dd6 2069 STRING_c_str(deviceData->messageHTTPrelativePath), /*relativePath: the message HTTP relative path*/
XinZhangMS 0:f7f1f0d76dd6 2070 deviceData->messageHTTPrequestHeaders, /*requestHttpHeadersHandle: message HTTP request headers created by _Create*/
XinZhangMS 0:f7f1f0d76dd6 2071 NULL, /*requestContent: NULL*/
XinZhangMS 0:f7f1f0d76dd6 2072 &statusCode, /*statusCode: a pointer to unsigned int which shall be later examined*/
XinZhangMS 0:f7f1f0d76dd6 2073 responseHTTPHeaders, /*responseHeadearsHandle: a new instance of HTTP headers*/
XinZhangMS 0:f7f1f0d76dd6 2074 responseContent /*responseContent: a new instance of buffer*/
XinZhangMS 0:f7f1f0d76dd6 2075 )) != HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 2076 {
XinZhangMS 0:f7f1f0d76dd6 2077 /*Codes_SRS_TRANSPORTMULTITHTTP_17_085: [If the call to HTTPAPIEX_SAS_ExecuteRequest did not executed successfully or building any part of the prerequisites of the call fails, then _DoWork shall advance to the next action in this description.] */
XinZhangMS 0:f7f1f0d76dd6 2078 LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
XinZhangMS 0:f7f1f0d76dd6 2079 }
XinZhangMS 0:f7f1f0d76dd6 2080 if (r == HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 2081 {
XinZhangMS 0:f7f1f0d76dd6 2082 /*HTTP dialogue was succesfull*/
XinZhangMS 0:f7f1f0d76dd6 2083 if (timeNow == (time_t)(-1))
XinZhangMS 0:f7f1f0d76dd6 2084 {
XinZhangMS 0:f7f1f0d76dd6 2085 deviceData->isFirstPoll = true;
XinZhangMS 0:f7f1f0d76dd6 2086 }
XinZhangMS 0:f7f1f0d76dd6 2087 else
XinZhangMS 0:f7f1f0d76dd6 2088 {
XinZhangMS 0:f7f1f0d76dd6 2089 deviceData->isFirstPoll = false;
XinZhangMS 0:f7f1f0d76dd6 2090 deviceData->lastPollTime = timeNow;
XinZhangMS 0:f7f1f0d76dd6 2091 }
XinZhangMS 0:f7f1f0d76dd6 2092 if (statusCode == 204)
XinZhangMS 0:f7f1f0d76dd6 2093 {
XinZhangMS 0:f7f1f0d76dd6 2094 /*Codes_SRS_TRANSPORTMULTITHTTP_17_086: [If the HTTPAPIEX_SAS_ExecuteRequest executed successfully then status code shall be examined. Any status code different than 200 causes _DoWork to advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 2095 /*this is an expected status code, means "no commands", but logging that creates panic*/
XinZhangMS 0:f7f1f0d76dd6 2096
XinZhangMS 0:f7f1f0d76dd6 2097 /*do nothing, advance to next action*/
XinZhangMS 0:f7f1f0d76dd6 2098 }
XinZhangMS 0:f7f1f0d76dd6 2099 else if (statusCode != 200)
XinZhangMS 0:f7f1f0d76dd6 2100 {
XinZhangMS 0:f7f1f0d76dd6 2101 /*Codes_SRS_TRANSPORTMULTITHTTP_17_086: [If the HTTPAPIEX_SAS_ExecuteRequest executed successfully then status code shall be examined. Any status code different than 200 causes _DoWork to advance to the next action.] */
XinZhangMS 0:f7f1f0d76dd6 2102 LogError("expected status code was 200, but actually was received %u... moving on", statusCode);
XinZhangMS 0:f7f1f0d76dd6 2103 }
XinZhangMS 0:f7f1f0d76dd6 2104 else
XinZhangMS 0:f7f1f0d76dd6 2105 {
XinZhangMS 0:f7f1f0d76dd6 2106 /*Codes_SRS_TRANSPORTMULTITHTTP_17_087: [If status code is 200, then _DoWork shall make a copy of the value of the "ETag" http header.]*/
XinZhangMS 0:f7f1f0d76dd6 2107 const char* etagValue = HTTPHeaders_FindHeaderValue(responseHTTPHeaders, "ETag");
XinZhangMS 0:f7f1f0d76dd6 2108 if (etagValue == NULL)
XinZhangMS 0:f7f1f0d76dd6 2109 {
XinZhangMS 0:f7f1f0d76dd6 2110 LogError("unable to find a received header called \"E-Tag\"");
XinZhangMS 0:f7f1f0d76dd6 2111 }
XinZhangMS 0:f7f1f0d76dd6 2112 else
XinZhangMS 0:f7f1f0d76dd6 2113 {
XinZhangMS 0:f7f1f0d76dd6 2114 /*Codes_SRS_TRANSPORTMULTITHTTP_17_088: [If no such header is found or is invalid, then _DoWork shall advance to the next action.]*/
XinZhangMS 0:f7f1f0d76dd6 2115 size_t etagsize = strlen(etagValue);
XinZhangMS 0:f7f1f0d76dd6 2116 if (
XinZhangMS 0:f7f1f0d76dd6 2117 (etagsize < 2) ||
XinZhangMS 0:f7f1f0d76dd6 2118 (etagValue[0] != '"') ||
XinZhangMS 0:f7f1f0d76dd6 2119 (etagValue[etagsize - 1] != '"')
XinZhangMS 0:f7f1f0d76dd6 2120 )
XinZhangMS 0:f7f1f0d76dd6 2121 {
XinZhangMS 0:f7f1f0d76dd6 2122 LogError("ETag is not a valid quoted string");
XinZhangMS 0:f7f1f0d76dd6 2123 }
XinZhangMS 0:f7f1f0d76dd6 2124 else
XinZhangMS 0:f7f1f0d76dd6 2125 {
XinZhangMS 0:f7f1f0d76dd6 2126 const unsigned char* resp_content;
XinZhangMS 0:f7f1f0d76dd6 2127 size_t resp_len;
XinZhangMS 0:f7f1f0d76dd6 2128 /*Codes_SRS_TRANSPORTMULTITHTTP_17_089: [_DoWork shall assemble an IOTHUBMESSAGE_HANDLE from the received HTTP content (using the responseContent buffer).] */
XinZhangMS 0:f7f1f0d76dd6 2129 resp_content = BUFFER_u_char(responseContent);
XinZhangMS 0:f7f1f0d76dd6 2130 resp_len = BUFFER_length(responseContent);
XinZhangMS 0:f7f1f0d76dd6 2131 IOTHUB_MESSAGE_HANDLE receivedMessage = IoTHubMessage_CreateFromByteArray(resp_content, resp_len);
XinZhangMS 0:f7f1f0d76dd6 2132 if (receivedMessage == NULL)
XinZhangMS 0:f7f1f0d76dd6 2133 {
XinZhangMS 0:f7f1f0d76dd6 2134 /*Codes_SRS_TRANSPORTMULTITHTTP_17_092: [If assembling the message fails in any way, then _DoWork shall "abandon" the message.]*/
XinZhangMS 0:f7f1f0d76dd6 2135 LogError("unable to IoTHubMessage_CreateFromByteArray, trying to abandon the message... ");
XinZhangMS 0:f7f1f0d76dd6 2136 if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
XinZhangMS 0:f7f1f0d76dd6 2137 {
XinZhangMS 0:f7f1f0d76dd6 2138 LogError("HTTP Transport layer failed to report ABANDON disposition");
XinZhangMS 0:f7f1f0d76dd6 2139 }
XinZhangMS 0:f7f1f0d76dd6 2140 }
XinZhangMS 0:f7f1f0d76dd6 2141 else
XinZhangMS 0:f7f1f0d76dd6 2142 {
XinZhangMS 0:f7f1f0d76dd6 2143 /*Codes_SRS_TRANSPORTMULTITHTTP_17_090: [All the HTTP headers of the form iothub-app-name:somecontent shall be transformed in message properties {name, somecontent}.]*/
XinZhangMS 0:f7f1f0d76dd6 2144 /*Codes_SRS_TRANSPORTMULTITHTTP_17_091: [The HTTP header of iothub-messageid shall be set in the MessageId.]*/
XinZhangMS 0:f7f1f0d76dd6 2145 size_t nHeaders;
XinZhangMS 0:f7f1f0d76dd6 2146 if (HTTPHeaders_GetHeaderCount(responseHTTPHeaders, &nHeaders) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 2147 {
XinZhangMS 0:f7f1f0d76dd6 2148 LogError("unable to get the count of HTTP headers");
XinZhangMS 0:f7f1f0d76dd6 2149 if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
XinZhangMS 0:f7f1f0d76dd6 2150 {
XinZhangMS 0:f7f1f0d76dd6 2151 LogError("HTTP Transport layer failed to report ABANDON disposition");
XinZhangMS 0:f7f1f0d76dd6 2152 }
XinZhangMS 0:f7f1f0d76dd6 2153 }
XinZhangMS 0:f7f1f0d76dd6 2154 else
XinZhangMS 0:f7f1f0d76dd6 2155 {
XinZhangMS 0:f7f1f0d76dd6 2156 size_t i;
XinZhangMS 0:f7f1f0d76dd6 2157 MAP_HANDLE properties = (nHeaders > 0) ? IoTHubMessage_Properties(receivedMessage) : NULL;
XinZhangMS 0:f7f1f0d76dd6 2158 for (i = 0; i < nHeaders; i++)
XinZhangMS 0:f7f1f0d76dd6 2159 {
XinZhangMS 0:f7f1f0d76dd6 2160 char* completeHeader;
XinZhangMS 0:f7f1f0d76dd6 2161 if (HTTPHeaders_GetHeader(responseHTTPHeaders, i, &completeHeader) != HTTP_HEADERS_OK)
XinZhangMS 0:f7f1f0d76dd6 2162 {
XinZhangMS 0:f7f1f0d76dd6 2163 break;
XinZhangMS 0:f7f1f0d76dd6 2164 }
XinZhangMS 0:f7f1f0d76dd6 2165 else
XinZhangMS 0:f7f1f0d76dd6 2166 {
XinZhangMS 0:f7f1f0d76dd6 2167 if (strncmp(IOTHUB_APP_PREFIX, completeHeader, strlen(IOTHUB_APP_PREFIX)) == 0)
XinZhangMS 0:f7f1f0d76dd6 2168 {
XinZhangMS 0:f7f1f0d76dd6 2169 /*looks like a property headers*/
XinZhangMS 0:f7f1f0d76dd6 2170 /*there's a guaranteed ':' in the completeHeader, by HTTP_HEADERS module*/
XinZhangMS 0:f7f1f0d76dd6 2171 char* whereIsColon = strchr(completeHeader, ':');
XinZhangMS 0:f7f1f0d76dd6 2172 if (whereIsColon != NULL)
XinZhangMS 0:f7f1f0d76dd6 2173 {
XinZhangMS 0:f7f1f0d76dd6 2174 *whereIsColon = '\0'; /*cut it down*/
XinZhangMS 0:f7f1f0d76dd6 2175 if (Map_AddOrUpdate(properties, completeHeader + strlen(IOTHUB_APP_PREFIX), whereIsColon + 2) != MAP_OK) /*whereIsColon+1 is a space because HTTPEHADERS outputs a ": " between name and value*/
XinZhangMS 0:f7f1f0d76dd6 2176 {
XinZhangMS 0:f7f1f0d76dd6 2177 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2178 break;
XinZhangMS 0:f7f1f0d76dd6 2179 }
XinZhangMS 0:f7f1f0d76dd6 2180 }
XinZhangMS 0:f7f1f0d76dd6 2181 }
XinZhangMS 0:f7f1f0d76dd6 2182 else if (strncmp(IOTHUB_MESSAGE_ID, completeHeader, strlen(IOTHUB_MESSAGE_ID)) == 0)
XinZhangMS 0:f7f1f0d76dd6 2183 {
XinZhangMS 0:f7f1f0d76dd6 2184 char* whereIsColon = strchr(completeHeader, ':');
XinZhangMS 0:f7f1f0d76dd6 2185 if (whereIsColon != NULL)
XinZhangMS 0:f7f1f0d76dd6 2186 {
XinZhangMS 0:f7f1f0d76dd6 2187 *whereIsColon = '\0'; /*cut it down*/
XinZhangMS 0:f7f1f0d76dd6 2188 if (IoTHubMessage_SetMessageId(receivedMessage, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 2189 {
XinZhangMS 0:f7f1f0d76dd6 2190 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2191 break;
XinZhangMS 0:f7f1f0d76dd6 2192 }
XinZhangMS 0:f7f1f0d76dd6 2193 }
XinZhangMS 0:f7f1f0d76dd6 2194 }
XinZhangMS 0:f7f1f0d76dd6 2195 else if (strncmp(IOTHUB_CORRELATION_ID, completeHeader, strlen(IOTHUB_CORRELATION_ID)) == 0)
XinZhangMS 0:f7f1f0d76dd6 2196 {
XinZhangMS 0:f7f1f0d76dd6 2197 char* whereIsColon = strchr(completeHeader, ':');
XinZhangMS 0:f7f1f0d76dd6 2198 if (whereIsColon != NULL)
XinZhangMS 0:f7f1f0d76dd6 2199 {
XinZhangMS 0:f7f1f0d76dd6 2200 *whereIsColon = '\0'; /*cut it down*/
XinZhangMS 0:f7f1f0d76dd6 2201 if (IoTHubMessage_SetCorrelationId(receivedMessage, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 2202 {
XinZhangMS 0:f7f1f0d76dd6 2203 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2204 break;
XinZhangMS 0:f7f1f0d76dd6 2205 }
XinZhangMS 0:f7f1f0d76dd6 2206 }
XinZhangMS 0:f7f1f0d76dd6 2207 }
XinZhangMS 0:f7f1f0d76dd6 2208 // Codes_SRS_TRANSPORTMULTITHTTP_09_003: [ The HTTP header value of `ContentType` shall be set in the `IoTHubMessage_SetContentTypeSystemProperty`. ]
XinZhangMS 0:f7f1f0d76dd6 2209 else if (strncmp(IOTHUB_CONTENT_TYPE_C2D, completeHeader, strlen(IOTHUB_CONTENT_TYPE_C2D)) == 0)
XinZhangMS 0:f7f1f0d76dd6 2210 {
XinZhangMS 0:f7f1f0d76dd6 2211 char* whereIsColon = strchr(completeHeader, ':');
XinZhangMS 0:f7f1f0d76dd6 2212 if (whereIsColon != NULL)
XinZhangMS 0:f7f1f0d76dd6 2213 {
XinZhangMS 0:f7f1f0d76dd6 2214 *whereIsColon = '\0'; /*cut it down*/
XinZhangMS 0:f7f1f0d76dd6 2215 if (IoTHubMessage_SetContentTypeSystemProperty(receivedMessage, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 2216 {
XinZhangMS 0:f7f1f0d76dd6 2217 LogError("Failed setting IoTHubMessage content-type");
XinZhangMS 0:f7f1f0d76dd6 2218 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2219 break;
XinZhangMS 0:f7f1f0d76dd6 2220 }
XinZhangMS 0:f7f1f0d76dd6 2221 }
XinZhangMS 0:f7f1f0d76dd6 2222 }
XinZhangMS 0:f7f1f0d76dd6 2223 // Codes_SRS_TRANSPORTMULTITHTTP_09_004: [ The HTTP header value of `ContentEncoding` shall be set in the `IoTHub_SetContentEncoding`. ]
XinZhangMS 0:f7f1f0d76dd6 2224 else if (strncmp(IOTHUB_CONTENT_ENCODING_C2D, completeHeader, strlen(IOTHUB_CONTENT_ENCODING_C2D)) == 0)
XinZhangMS 0:f7f1f0d76dd6 2225 {
XinZhangMS 0:f7f1f0d76dd6 2226 char* whereIsColon = strchr(completeHeader, ':');
XinZhangMS 0:f7f1f0d76dd6 2227 if (whereIsColon != NULL)
XinZhangMS 0:f7f1f0d76dd6 2228 {
XinZhangMS 0:f7f1f0d76dd6 2229 *whereIsColon = '\0'; /*cut it down*/
XinZhangMS 0:f7f1f0d76dd6 2230 if (IoTHubMessage_SetContentEncodingSystemProperty(receivedMessage, whereIsColon + 2) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 2231 {
XinZhangMS 0:f7f1f0d76dd6 2232 LogError("Failed setting IoTHubMessage content-encoding");
XinZhangMS 0:f7f1f0d76dd6 2233 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2234 break;
XinZhangMS 0:f7f1f0d76dd6 2235 }
XinZhangMS 0:f7f1f0d76dd6 2236 }
XinZhangMS 0:f7f1f0d76dd6 2237 }
XinZhangMS 0:f7f1f0d76dd6 2238
XinZhangMS 0:f7f1f0d76dd6 2239 free(completeHeader);
XinZhangMS 0:f7f1f0d76dd6 2240 }
XinZhangMS 0:f7f1f0d76dd6 2241 }
XinZhangMS 0:f7f1f0d76dd6 2242
XinZhangMS 0:f7f1f0d76dd6 2243 if (i < nHeaders)
XinZhangMS 0:f7f1f0d76dd6 2244 {
XinZhangMS 0:f7f1f0d76dd6 2245 if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
XinZhangMS 0:f7f1f0d76dd6 2246 {
XinZhangMS 0:f7f1f0d76dd6 2247 LogError("HTTP Transport layer failed to report ABANDON disposition");
XinZhangMS 0:f7f1f0d76dd6 2248 }
XinZhangMS 0:f7f1f0d76dd6 2249 }
XinZhangMS 0:f7f1f0d76dd6 2250 else
XinZhangMS 0:f7f1f0d76dd6 2251 {
XinZhangMS 0:f7f1f0d76dd6 2252 MESSAGE_CALLBACK_INFO* messageData = MESSAGE_CALLBACK_INFO_Create(receivedMessage, handleData, deviceData, etagValue);
XinZhangMS 0:f7f1f0d76dd6 2253 if (messageData == NULL)
XinZhangMS 0:f7f1f0d76dd6 2254 {
XinZhangMS 0:f7f1f0d76dd6 2255 /*Codes_SRS_TRANSPORTMULTITHTTP_10_006: [If assembling the transport context fails, _DoWork shall "abandon" the message.] */
XinZhangMS 0:f7f1f0d76dd6 2256 LogError("failed to assemble callback info");
XinZhangMS 0:f7f1f0d76dd6 2257 if (!abandonOrAcceptMessage(handleData, deviceData, etagValue, IOTHUBMESSAGE_ABANDONED))
XinZhangMS 0:f7f1f0d76dd6 2258 {
XinZhangMS 0:f7f1f0d76dd6 2259 LogError("HTTP Transport layer failed to report ABANDON disposition");
XinZhangMS 0:f7f1f0d76dd6 2260 }
XinZhangMS 0:f7f1f0d76dd6 2261 }
XinZhangMS 0:f7f1f0d76dd6 2262 else
XinZhangMS 0:f7f1f0d76dd6 2263 {
XinZhangMS 0:f7f1f0d76dd6 2264 bool abandon;
XinZhangMS 0:f7f1f0d76dd6 2265 if (IoTHubClientCore_LL_MessageCallback(iotHubClientHandle, messageData))
XinZhangMS 0:f7f1f0d76dd6 2266 {
XinZhangMS 0:f7f1f0d76dd6 2267 abandon = false;
XinZhangMS 0:f7f1f0d76dd6 2268 }
XinZhangMS 0:f7f1f0d76dd6 2269 else
XinZhangMS 0:f7f1f0d76dd6 2270 {
XinZhangMS 0:f7f1f0d76dd6 2271 LogError("IoTHubClientCore_LL_MessageCallback failed");
XinZhangMS 0:f7f1f0d76dd6 2272 abandon = true;
XinZhangMS 0:f7f1f0d76dd6 2273 }
XinZhangMS 0:f7f1f0d76dd6 2274
XinZhangMS 0:f7f1f0d76dd6 2275 /*Codes_SRS_TRANSPORTMULTITHTTP_17_096: [If IoTHubClientCore_LL_MessageCallback returns false then _DoWork shall "abandon" the message.] */
XinZhangMS 0:f7f1f0d76dd6 2276 if (abandon)
XinZhangMS 0:f7f1f0d76dd6 2277 {
XinZhangMS 0:f7f1f0d76dd6 2278 (void)IoTHubTransportHttp_SendMessageDisposition(messageData, IOTHUBMESSAGE_ABANDONED);
XinZhangMS 0:f7f1f0d76dd6 2279 }
XinZhangMS 0:f7f1f0d76dd6 2280 }
XinZhangMS 0:f7f1f0d76dd6 2281 }
XinZhangMS 0:f7f1f0d76dd6 2282 }
XinZhangMS 0:f7f1f0d76dd6 2283 IoTHubMessage_Destroy(receivedMessage);
XinZhangMS 0:f7f1f0d76dd6 2284 }
XinZhangMS 0:f7f1f0d76dd6 2285 }
XinZhangMS 0:f7f1f0d76dd6 2286 }
XinZhangMS 0:f7f1f0d76dd6 2287 }
XinZhangMS 0:f7f1f0d76dd6 2288 }
XinZhangMS 0:f7f1f0d76dd6 2289 BUFFER_delete(responseContent);
XinZhangMS 0:f7f1f0d76dd6 2290 }
XinZhangMS 0:f7f1f0d76dd6 2291 HTTPHeaders_Free(responseHTTPHeaders);
XinZhangMS 0:f7f1f0d76dd6 2292 }
XinZhangMS 0:f7f1f0d76dd6 2293 }
XinZhangMS 0:f7f1f0d76dd6 2294 else
XinZhangMS 0:f7f1f0d76dd6 2295 {
XinZhangMS 0:f7f1f0d76dd6 2296 /*isPollingAllowed is false... */
XinZhangMS 0:f7f1f0d76dd6 2297 /*do nothing "shall be ignored*/
XinZhangMS 0:f7f1f0d76dd6 2298 }
XinZhangMS 0:f7f1f0d76dd6 2299 }
XinZhangMS 0:f7f1f0d76dd6 2300 }
XinZhangMS 0:f7f1f0d76dd6 2301
XinZhangMS 0:f7f1f0d76dd6 2302 static IOTHUB_PROCESS_ITEM_RESULT IoTHubTransportHttp_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
XinZhangMS 0:f7f1f0d76dd6 2303 {
XinZhangMS 0:f7f1f0d76dd6 2304 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 2305 (void)item_type;
XinZhangMS 0:f7f1f0d76dd6 2306 (void)iothub_item;
XinZhangMS 0:f7f1f0d76dd6 2307 LogError("Currently Not Supported.");
XinZhangMS 0:f7f1f0d76dd6 2308 return IOTHUB_PROCESS_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2309 }
XinZhangMS 0:f7f1f0d76dd6 2310
XinZhangMS 0:f7f1f0d76dd6 2311 static void IoTHubTransportHttp_DoWork(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
XinZhangMS 0:f7f1f0d76dd6 2312 {
XinZhangMS 0:f7f1f0d76dd6 2313 /*Codes_SRS_TRANSPORTMULTITHTTP_17_049: [ If handle is NULL, then IoTHubTransportHttp_DoWork shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 2314 /*Codes_SRS_TRANSPORTMULTITHTTP_17_140: [ If iotHubClientHandle is NULL, then IoTHubTransportHttp_DoWork shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 2315
XinZhangMS 0:f7f1f0d76dd6 2316 (void)iotHubClientHandle; // use the perDevice handle.
XinZhangMS 0:f7f1f0d76dd6 2317 if (handle != NULL)
XinZhangMS 0:f7f1f0d76dd6 2318 {
XinZhangMS 0:f7f1f0d76dd6 2319 HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 2320 IOTHUB_DEVICE_HANDLE* listItem;
XinZhangMS 0:f7f1f0d76dd6 2321 size_t deviceListSize = VECTOR_size(handleData->perDeviceList);
XinZhangMS 0:f7f1f0d76dd6 2322 /*Codes_SRS_TRANSPORTMULTITHTTP_17_052: [ IoTHubTransportHttp_DoWork shall perform a round-robin loop through every deviceHandle in the transport device list, using the iotHubClientHandle field saved in the IOTHUB_DEVICE_HANDLE. ]*/
XinZhangMS 0:f7f1f0d76dd6 2323 /*Codes_SRS_TRANSPORTMULTITHTTP_17_050: [ IoTHubTransportHttp_DoWork shall call loop through the device list. ] */
XinZhangMS 0:f7f1f0d76dd6 2324 /*Codes_SRS_TRANSPORTMULTITHTTP_17_051: [ IF the list is empty, then IoTHubTransportHttp_DoWork shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 2325 for (size_t i = 0; i < deviceListSize; i++)
XinZhangMS 0:f7f1f0d76dd6 2326 {
XinZhangMS 0:f7f1f0d76dd6 2327 listItem = (IOTHUB_DEVICE_HANDLE *)VECTOR_element(handleData->perDeviceList, i);
XinZhangMS 0:f7f1f0d76dd6 2328 HTTPTRANSPORT_PERDEVICE_DATA* perDeviceItem = *(HTTPTRANSPORT_PERDEVICE_DATA**)(listItem);
XinZhangMS 0:f7f1f0d76dd6 2329 DoEvent(handleData, perDeviceItem, perDeviceItem->iotHubClientHandle);
XinZhangMS 0:f7f1f0d76dd6 2330 DoMessages(handleData, perDeviceItem, perDeviceItem->iotHubClientHandle);
XinZhangMS 0:f7f1f0d76dd6 2331
XinZhangMS 0:f7f1f0d76dd6 2332 }
XinZhangMS 0:f7f1f0d76dd6 2333 }
XinZhangMS 0:f7f1f0d76dd6 2334 else
XinZhangMS 0:f7f1f0d76dd6 2335 {
XinZhangMS 0:f7f1f0d76dd6 2336 LogError("Invalid Argument NULL call on DoWork.");
XinZhangMS 0:f7f1f0d76dd6 2337 }
XinZhangMS 0:f7f1f0d76dd6 2338 }
XinZhangMS 0:f7f1f0d76dd6 2339
XinZhangMS 0:f7f1f0d76dd6 2340 static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
XinZhangMS 0:f7f1f0d76dd6 2341 {
XinZhangMS 0:f7f1f0d76dd6 2342 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 2343
XinZhangMS 0:f7f1f0d76dd6 2344 if (handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 2345 {
XinZhangMS 0:f7f1f0d76dd6 2346 /*Codes_SRS_TRANSPORTMULTITHTTP_17_111: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter. ]*/
XinZhangMS 0:f7f1f0d76dd6 2347 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2348 LogError("Invalid handle to IoTHubClient HTTP transport instance.");
XinZhangMS 0:f7f1f0d76dd6 2349 }
XinZhangMS 0:f7f1f0d76dd6 2350 else if (iotHubClientStatus == NULL)
XinZhangMS 0:f7f1f0d76dd6 2351 {
XinZhangMS 0:f7f1f0d76dd6 2352 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2353 LogError("Invalid pointer to output parameter IOTHUB_CLIENT_STATUS.");
XinZhangMS 0:f7f1f0d76dd6 2354 }
XinZhangMS 0:f7f1f0d76dd6 2355 else
XinZhangMS 0:f7f1f0d76dd6 2356 {
XinZhangMS 0:f7f1f0d76dd6 2357 /*Codes_SRS_TRANSPORTMULTITHTTP_17_138: [ IoTHubTransportHttp_GetSendStatus shall locate deviceHandle in the transport device list by calling list_find_if. ]*/
XinZhangMS 0:f7f1f0d76dd6 2358 IOTHUB_DEVICE_HANDLE* listItem = get_perDeviceDataItem(handle);
XinZhangMS 0:f7f1f0d76dd6 2359 if (listItem == NULL)
XinZhangMS 0:f7f1f0d76dd6 2360 {
XinZhangMS 0:f7f1f0d76dd6 2361 /*Codes_SRS_TRANSPORTMULTITHTTP_17_139: [ If the device structure is not found, then this function shall fail and return with IOTHUB_CLIENT_INVALID_ARG. ]*/
XinZhangMS 0:f7f1f0d76dd6 2362 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2363 LogError("Device not found in transport list.");
XinZhangMS 0:f7f1f0d76dd6 2364 }
XinZhangMS 0:f7f1f0d76dd6 2365 else
XinZhangMS 0:f7f1f0d76dd6 2366 {
XinZhangMS 0:f7f1f0d76dd6 2367 HTTPTRANSPORT_PERDEVICE_DATA* deviceData = (HTTPTRANSPORT_PERDEVICE_DATA*)(*listItem);
XinZhangMS 0:f7f1f0d76dd6 2368 /* Codes_SRS_TRANSPORTMULTITHTTP_17_113: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent. ] */
XinZhangMS 0:f7f1f0d76dd6 2369 if (!DList_IsListEmpty(deviceData->waitingToSend))
XinZhangMS 0:f7f1f0d76dd6 2370 {
XinZhangMS 0:f7f1f0d76dd6 2371 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
XinZhangMS 0:f7f1f0d76dd6 2372 }
XinZhangMS 0:f7f1f0d76dd6 2373 /* Codes_SRS_TRANSPORTMULTITHTTP_17_112: [ IoTHubTransportHttp_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent. ] */
XinZhangMS 0:f7f1f0d76dd6 2374 else
XinZhangMS 0:f7f1f0d76dd6 2375 {
XinZhangMS 0:f7f1f0d76dd6 2376 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
XinZhangMS 0:f7f1f0d76dd6 2377 }
XinZhangMS 0:f7f1f0d76dd6 2378 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2379 }
XinZhangMS 0:f7f1f0d76dd6 2380 }
XinZhangMS 0:f7f1f0d76dd6 2381
XinZhangMS 0:f7f1f0d76dd6 2382 return result;
XinZhangMS 0:f7f1f0d76dd6 2383 }
XinZhangMS 0:f7f1f0d76dd6 2384
XinZhangMS 0:f7f1f0d76dd6 2385 static IOTHUB_CLIENT_RESULT IoTHubTransportHttp_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
XinZhangMS 0:f7f1f0d76dd6 2386 {
XinZhangMS 0:f7f1f0d76dd6 2387 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 2388 /*Codes_SRS_TRANSPORTMULTITHTTP_17_114: [If handle parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 2389 /*Codes_SRS_TRANSPORTMULTITHTTP_17_115: [If option parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 2390 /*Codes_SRS_TRANSPORTMULTITHTTP_17_116: [If value parameter is NULL then IoTHubTransportHttp_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 2391 if (
XinZhangMS 0:f7f1f0d76dd6 2392 (handle == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 2393 (option == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 2394 (value == NULL)
XinZhangMS 0:f7f1f0d76dd6 2395 )
XinZhangMS 0:f7f1f0d76dd6 2396 {
XinZhangMS 0:f7f1f0d76dd6 2397 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2398 LogError("invalid parameter (NULL) passed to IoTHubTransportHttp_SetOption");
XinZhangMS 0:f7f1f0d76dd6 2399 }
XinZhangMS 0:f7f1f0d76dd6 2400 else
XinZhangMS 0:f7f1f0d76dd6 2401 {
XinZhangMS 0:f7f1f0d76dd6 2402 HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 2403 /*Codes_SRS_TRANSPORTMULTITHTTP_17_120: ["Batching"] */
XinZhangMS 0:f7f1f0d76dd6 2404 if (strcmp(OPTION_BATCHING, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 2405 {
XinZhangMS 0:f7f1f0d76dd6 2406 /*Codes_SRS_TRANSPORTMULTITHTTP_17_117: [If optionName is an option handled by IoTHubTransportHttp then it shall be set.] */
XinZhangMS 0:f7f1f0d76dd6 2407 handleData->doBatchedTransfers = *(bool*)value;
XinZhangMS 0:f7f1f0d76dd6 2408 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2409 }
XinZhangMS 0:f7f1f0d76dd6 2410 /*Codes_SRS_TRANSPORTMULTITHTTP_17_121: ["MinimumPollingTime"] */
XinZhangMS 0:f7f1f0d76dd6 2411 else if (strcmp(OPTION_MIN_POLLING_TIME, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 2412 {
XinZhangMS 0:f7f1f0d76dd6 2413 handleData->getMinimumPollingTime = *(unsigned int*)value;
XinZhangMS 0:f7f1f0d76dd6 2414 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2415 }
XinZhangMS 0:f7f1f0d76dd6 2416 else
XinZhangMS 0:f7f1f0d76dd6 2417 {
XinZhangMS 0:f7f1f0d76dd6 2418 /*Codes_SRS_TRANSPORTMULTITHTTP_17_126: [ "TrustedCerts"] */
XinZhangMS 0:f7f1f0d76dd6 2419 /*Codes_SRS_TRANSPORTMULTITHTTP_17_127: [ NULL shall be allowed. ]*/
XinZhangMS 0:f7f1f0d76dd6 2420 /*Codes_SRS_TRANSPORTMULTITHTTP_17_129: [ This option shall passed down to the lower layer by calling HTTPAPIEX_SetOption. ]*/
XinZhangMS 0:f7f1f0d76dd6 2421 /*Codes_SRS_TRANSPORTMULTITHTTP_17_118: [Otherwise, IoTHubTransport_Http shall call HTTPAPIEX_SetOption with the same parameters and return the translated code.] */
XinZhangMS 0:f7f1f0d76dd6 2422 HTTPAPIEX_RESULT HTTPAPIEX_result = HTTPAPIEX_SetOption(handleData->httpApiExHandle, option, value);
XinZhangMS 0:f7f1f0d76dd6 2423 /*Codes_SRS_TRANSPORTMULTITHTTP_17_119: [The following table translates HTTPAPIEX return codes to IOTHUB_CLIENT_RESULT return codes:] */
XinZhangMS 0:f7f1f0d76dd6 2424 if (HTTPAPIEX_result == HTTPAPIEX_OK)
XinZhangMS 0:f7f1f0d76dd6 2425 {
XinZhangMS 0:f7f1f0d76dd6 2426 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2427 }
XinZhangMS 0:f7f1f0d76dd6 2428 else if (HTTPAPIEX_result == HTTPAPIEX_INVALID_ARG)
XinZhangMS 0:f7f1f0d76dd6 2429 {
XinZhangMS 0:f7f1f0d76dd6 2430 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2431 LogError("HTTPAPIEX_SetOption failed");
XinZhangMS 0:f7f1f0d76dd6 2432 }
XinZhangMS 0:f7f1f0d76dd6 2433 else
XinZhangMS 0:f7f1f0d76dd6 2434 {
XinZhangMS 0:f7f1f0d76dd6 2435 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2436 LogError("HTTPAPIEX_SetOption failed");
XinZhangMS 0:f7f1f0d76dd6 2437 }
XinZhangMS 0:f7f1f0d76dd6 2438 }
XinZhangMS 0:f7f1f0d76dd6 2439 }
XinZhangMS 0:f7f1f0d76dd6 2440 return result;
XinZhangMS 0:f7f1f0d76dd6 2441 }
XinZhangMS 0:f7f1f0d76dd6 2442
XinZhangMS 0:f7f1f0d76dd6 2443 static STRING_HANDLE IoTHubTransportHttp_GetHostname(TRANSPORT_LL_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2444 {
XinZhangMS 0:f7f1f0d76dd6 2445 STRING_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 2446 /*Codes_SRS_TRANSPORTMULTITHTTP_02_001: [ If handle is NULL then IoTHubTransportHttp_GetHostname shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 2447 if (handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 2448 {
XinZhangMS 0:f7f1f0d76dd6 2449 LogError("invalid parameter handle=%p", handle);
XinZhangMS 0:f7f1f0d76dd6 2450 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2451 }
XinZhangMS 0:f7f1f0d76dd6 2452 /*Codes_SRS_TRANSPORTMULTITHTTP_02_002: [ Otherwise IoTHubTransportHttp_GetHostname shall return a non-NULL STRING_HANDLE containing the hostname. ]*/
XinZhangMS 0:f7f1f0d76dd6 2453 else if ((result = STRING_clone(((HTTPTRANSPORT_HANDLE_DATA*)(handle))->hostName)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2454 {
XinZhangMS 0:f7f1f0d76dd6 2455 LogError("Cannot provide the target host name (STRING_clone failed).");
XinZhangMS 0:f7f1f0d76dd6 2456 }
XinZhangMS 0:f7f1f0d76dd6 2457
XinZhangMS 0:f7f1f0d76dd6 2458 return result;
XinZhangMS 0:f7f1f0d76dd6 2459 }
XinZhangMS 0:f7f1f0d76dd6 2460
XinZhangMS 0:f7f1f0d76dd6 2461 static int IoTHubTransportHttp_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
XinZhangMS 0:f7f1f0d76dd6 2462 {
XinZhangMS 0:f7f1f0d76dd6 2463 int result;
XinZhangMS 0:f7f1f0d76dd6 2464 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 2465 (void)retryPolicy;
XinZhangMS 0:f7f1f0d76dd6 2466 (void)retryTimeoutLimitInSeconds;
XinZhangMS 0:f7f1f0d76dd6 2467
XinZhangMS 0:f7f1f0d76dd6 2468 /* Retry Policy is not currently not available for HTTP */
XinZhangMS 0:f7f1f0d76dd6 2469
XinZhangMS 0:f7f1f0d76dd6 2470 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2471 return result;
XinZhangMS 0:f7f1f0d76dd6 2472 }
XinZhangMS 0:f7f1f0d76dd6 2473
XinZhangMS 0:f7f1f0d76dd6 2474 static int IotHubTransportHttp_Subscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2475 {
XinZhangMS 0:f7f1f0d76dd6 2476 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 2477 LogError("HTTP does not support input queues");
XinZhangMS 0:f7f1f0d76dd6 2478 return __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2479 }
XinZhangMS 0:f7f1f0d76dd6 2480
XinZhangMS 0:f7f1f0d76dd6 2481 static void IotHubTransportHttp_Unsubscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2482 {
XinZhangMS 0:f7f1f0d76dd6 2483 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 2484 LogError("HTTP does not support input queues");
XinZhangMS 0:f7f1f0d76dd6 2485 }
XinZhangMS 0:f7f1f0d76dd6 2486
XinZhangMS 0:f7f1f0d76dd6 2487
XinZhangMS 0:f7f1f0d76dd6 2488 /*Codes_SRS_TRANSPORTMULTITHTTP_17_125: [This function shall return a pointer to a structure of type TRANSPORT_PROVIDER having the following values for its fields:] */
XinZhangMS 0:f7f1f0d76dd6 2489 static TRANSPORT_PROVIDER thisTransportProvider =
XinZhangMS 0:f7f1f0d76dd6 2490 {
XinZhangMS 0:f7f1f0d76dd6 2491 IoTHubTransportHttp_SendMessageDisposition, /*pfIotHubTransport_SendMessageDisposition IoTHubTransport_SendMessageDisposition;*/
XinZhangMS 0:f7f1f0d76dd6 2492 IoTHubTransportHttp_Subscribe_DeviceMethod, /*pfIoTHubTransport_Subscribe_DeviceMethod IoTHubTransport_Subscribe_DeviceMethod;*/
XinZhangMS 0:f7f1f0d76dd6 2493 IoTHubTransportHttp_Unsubscribe_DeviceMethod, /*pfIoTHubTransport_Unsubscribe_DeviceMethod IoTHubTransport_Unsubscribe_DeviceMethod;*/
XinZhangMS 0:f7f1f0d76dd6 2494 IoTHubTransportHttp_DeviceMethod_Response, /*pfIoTHubTransport_DeviceMethod_Response IoTHubTransport_DeviceMethod_Response;*/
XinZhangMS 0:f7f1f0d76dd6 2495 IoTHubTransportHttp_Subscribe_DeviceTwin, /*pfIoTHubTransport_Subscribe_DeviceTwin IoTHubTransport_Subscribe_DeviceTwin;*/
XinZhangMS 0:f7f1f0d76dd6 2496 IoTHubTransportHttp_Unsubscribe_DeviceTwin, /*pfIoTHubTransport_Unsubscribe_DeviceTwin IoTHubTransport_Unsubscribe_DeviceTwin;*/
XinZhangMS 0:f7f1f0d76dd6 2497 IoTHubTransportHttp_ProcessItem, /*pfIoTHubTransport_ProcessItem IoTHubTransport_ProcessItem;*/
XinZhangMS 0:f7f1f0d76dd6 2498 IoTHubTransportHttp_GetHostname, /*pfIoTHubTransport_GetHostname IoTHubTransport_GetHostname;*/
XinZhangMS 0:f7f1f0d76dd6 2499 IoTHubTransportHttp_SetOption, /*pfIoTHubTransport_SetOption IoTHubTransport_SetOption;*/
XinZhangMS 0:f7f1f0d76dd6 2500 IoTHubTransportHttp_Create, /*pfIoTHubTransport_Create IoTHubTransport_Create;*/
XinZhangMS 0:f7f1f0d76dd6 2501 IoTHubTransportHttp_Destroy, /*pfIoTHubTransport_Destroy IoTHubTransport_Destroy;*/
XinZhangMS 0:f7f1f0d76dd6 2502 IoTHubTransportHttp_Register, /*pfIotHubTransport_Register IoTHubTransport_Register;*/
XinZhangMS 0:f7f1f0d76dd6 2503 IoTHubTransportHttp_Unregister, /*pfIotHubTransport_Unregister IoTHubTransport_Unegister;*/
XinZhangMS 0:f7f1f0d76dd6 2504 IoTHubTransportHttp_Subscribe, /*pfIoTHubTransport_Subscribe IoTHubTransport_Subscribe;*/
XinZhangMS 0:f7f1f0d76dd6 2505 IoTHubTransportHttp_Unsubscribe, /*pfIoTHubTransport_Unsubscribe IoTHubTransport_Unsubscribe;*/
XinZhangMS 0:f7f1f0d76dd6 2506 IoTHubTransportHttp_DoWork, /*pfIoTHubTransport_DoWork IoTHubTransport_DoWork;*/
XinZhangMS 0:f7f1f0d76dd6 2507 IoTHubTransportHttp_SetRetryPolicy, /*pfIoTHubTransport_DoWork IoTHubTransport_SetRetryPolicy;*/
XinZhangMS 0:f7f1f0d76dd6 2508 IoTHubTransportHttp_GetSendStatus, /*pfIoTHubTransport_GetSendStatus IoTHubTransport_GetSendStatus;*/
XinZhangMS 0:f7f1f0d76dd6 2509 IotHubTransportHttp_Subscribe_InputQueue, /*pfIoTHubTransport_Subscribe_InputQueue IoTHubTransport_Subscribe_InputQueue; */
XinZhangMS 0:f7f1f0d76dd6 2510 IotHubTransportHttp_Unsubscribe_InputQueue /*pfIoTHubTransport_Unsubscribe_InputQueue IoTHubTransport_Unsubscribe_InputQueue; */
XinZhangMS 0:f7f1f0d76dd6 2511 };
XinZhangMS 0:f7f1f0d76dd6 2512
XinZhangMS 0:f7f1f0d76dd6 2513 const TRANSPORT_PROVIDER* HTTP_Protocol(void)
XinZhangMS 0:f7f1f0d76dd6 2514 {
XinZhangMS 0:f7f1f0d76dd6 2515 return &thisTransportProvider;
XinZhangMS 0:f7f1f0d76dd6 2516 }