static void sendMsgComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transportState, IOTHUB_BATCHSTATE_RESULT batchResult) { DLIST_ENTRY messageCompleted; DList_InitializeListHead(&messageCompleted); DList_InsertTailList(&messageCompleted, &(iothubMsgList->entry)); IoTHubClient_LL_SendComplete(transportState->llClientHandle, &messageCompleted, batchResult); }
int MESSAGE_QUEUE_push(MESSAGE_QUEUE_HANDLE handle, MESSAGE_HANDLE element) { int result; if (handle == NULL || element == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_007: [ MESSAGE_QUEUE_push shall return a non-zero value if handle or element are NULL. ]*/ LogError("invalid argument - handle(%p), element(%p).", handle, element); result = __LINE__; } else { MESSAGE_QUEUE_STORAGE* temp = (MESSAGE_QUEUE_STORAGE*)malloc(sizeof(MESSAGE_QUEUE_STORAGE)); if (temp == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_009: [ MESSAGE_QUEUE_push shall return a non-zero value if any system call fails. ]*/ LogError("malloc failed."); result = __LINE__; } else { DList_InitializeListHead((PDLIST_ENTRY)temp); temp->message = element; /*Codes_SRS_MESSAGE_QUEUE_17_011: [ Messages shall be pushed into the queue in a first-in-first-out order. ]*/ DList_AppendTailList((PDLIST_ENTRY)&(handle->queue_head), (PDLIST_ENTRY)temp); /*Codes_SRS_MESSAGE_QUEUE_17_008: [ MESSAGE_QUEUE_push shall return zero on success. ]*/ result = 0; } } return result; }
IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_Create(const IOTHUB_CLIENT_CONFIG* config) { IOTHUB_CLIENT_LL_HANDLE result; /*Codes_SRS_IOTHUBCLIENT_LL_02_001: [IoTHubClient_LL_Create shall return NULL if config parameter is NULL or protocol field is NULL.]*/ if ( (config == NULL) || (config->protocol == NULL) ) { result = NULL; LogError("invalid configuration (NULL detected)\r\n"); } else { IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); if (handleData == NULL) { LogError("malloc failed\r\n"); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_004: [Otherwise IoTHubClient_LL_Create shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ IOTHUBTRANSPORT_CONFIG lowerLayerConfig; DList_InitializeListHead(&(handleData->waitingToSend)); handleData->IoTHubTransport_SetOption = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_SetOption; handleData->IoTHubTransport_Create = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_Create; handleData->IoTHubTransport_Destroy = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_Destroy; handleData->IoTHubTransport_Subscribe = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_Subscribe; handleData->IoTHubTransport_Unsubscribe = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_Unsubscribe; handleData->IoTHubTransport_DoWork = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_DoWork; handleData->IoTHubTransport_GetSendStatus = ((TRANSPORT_PROVIDER*)config->protocol())->IoTHubTransport_GetSendStatus; handleData->messageCallback = NULL; handleData->messageUserContextCallback = NULL; handleData->lastMessageReceiveTime = INDEFINITE_TIME; /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClient_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/ lowerLayerConfig.upperConfig = config; lowerLayerConfig.waitingToSend = &(handleData->waitingToSend); /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClient_LL_Create shall fail and return NULL.] */ if ((handleData->transportHandle = handleData->IoTHubTransport_Create(&lowerLayerConfig)) == NULL) { LogError("underlying transport failed\r\n"); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */ result = handleData; } } } return result; }
MESSAGE_QUEUE_HANDLE MESSAGE_QUEUE_create() { MESSAGE_QUEUE_HANDLE_DATA* result; result = (MESSAGE_QUEUE_HANDLE_DATA*)malloc(sizeof(MESSAGE_QUEUE_HANDLE_DATA)); if (result == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_003: [ On a failure, MESSAGE_QUEUE_create shall return NULL. ]*/ LogError("malloc failed."); } else { /*Codes_SRS_MESSAGE_QUEUE_17_001: [ On a successful call, MESSAGE_QUEUE_create shall return a non-NULL value in MESSAGE_QUEUE_HANDLE. ]*/ /*Codes_SRS_MESSAGE_QUEUE_17_002: [ A newly created message queue shall be empty. ]*/ DList_InitializeListHead((PDLIST_ENTRY)&(result->queue_head)); result->queue_head.message = NULL; } return result; }
IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config) { IOTHUB_CLIENT_LL_HANDLE result; /*Codes_SRS_IOTHUBCLIENT_LL_17_001: [IoTHubClient_LL_CreateWithTransport shall return NULL if config parameter is NULL, or protocol field is NULL or transportHandle is NULL.]*/ if ( (config == NULL) || (config->protocol == NULL) || (config->transportHandle == NULL) ) { result = NULL; LogError("invalid configuration (NULL detected)"); } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_002: [IoTHubClient_LL_CreateWithTransport shall allocate data for the IOTHUB_CLIENT_LL_HANDLE.]*/ IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); if (handleData == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_17_003: [If allocation fails, the function shall fail and return NULL.] */ LogError("malloc failed"); result = NULL; } else { handleData->uploadToBlobHandle = NULL; /*Codes_SRS_IOTHUBCLIENT_LL_02_047: [ IoTHubClient_LL_CreateWithTransport shall create a TICK_COUNTER_HANDLE. ]*/ if ((handleData->tickCounter = tickcounter_create()) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_048: [ If creating the handle fails, then IoTHubClient_LL_CreateWithTransport shall fail and return NULL ]*/ LogError("unable to get a tickcounter"); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_004: [IoTHubClient_LL_CreateWithTransport shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ DList_InitializeListHead(&(handleData->waitingToSend)); setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol()); handleData->messageCallback = NULL; handleData->messageUserContextCallback = NULL; handleData->lastMessageReceiveTime = INDEFINITE_TIME; handleData->transportHandle = config->transportHandle; IOTHUB_DEVICE_CONFIG deviceConfig; deviceConfig.deviceId = config->deviceId; deviceConfig.deviceKey = config->deviceKey; deviceConfig.deviceSasToken = config->deviceSasToken; /*Codes_SRS_IOTHUBCLIENT_LL_17_006: [IoTHubClient_LL_CreateWithTransport shall call the transport _Register function with the IOTHUB_DEVICE_CONFIG populated structure and waitingToSend list.]*/ if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(config->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_17_007: [If the _Register function fails, this function shall fail and return NULL.]*/ LogError("Registering device in transport failed"); tickcounter_destroy(handleData->tickCounter); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_005: [IoTHubClient_LL_CreateWithTransport shall save the transport handle and mark this transport as shared.]*/ handleData->isSharedTransport = true; /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/ handleData->currentMessageTimeout = 0; result = handleData; } } } } return result; }
IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_Create(const IOTHUB_CLIENT_CONFIG* config) { IOTHUB_CLIENT_LL_HANDLE result; /*Codes_SRS_IOTHUBCLIENT_LL_02_001: [IoTHubClient_LL_Create shall return NULL if config parameter is NULL or protocol field is NULL.]*/ if( (config == NULL) || (config->protocol == NULL) ) { result = NULL; LogError("invalid configuration (NULL detected)"); } else { IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); if (handleData == NULL) { LogError("malloc failed"); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_094: [ IoTHubClient_LL_Create shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/ /*Codes_SRS_IOTHUBCLIENT_LL_02_092: [ IoTHubClient_LL_CreateFromConnectionString shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/ handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(config); if (handleData->uploadToBlobHandle == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_093: [ If creating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateFromConnectionString shall fail and return NULL. ]*/ /*Codes_SRS_IOTHUBCLIENT_LL_02_095: [ If creating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_Create shall fail and return NULL. ]*/ LogError("unable to IoTHubClient_LL_UploadToBlob_Create"); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_045: [ Otherwise IoTHubClient_LL_Create shall create a new TICK_COUNTER_HANDLE ]*/ if ((handleData->tickCounter = tickcounter_create()) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_046: [ If creating the TICK_COUNTER_HANDLE fails then IoTHubClient_LL_Create shall fail and return NULL. ]*/ IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); LogError("unable to get a tickcounter"); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_004: [Otherwise IoTHubClient_LL_Create shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ IOTHUBTRANSPORT_CONFIG lowerLayerConfig; DList_InitializeListHead(&(handleData->waitingToSend)); setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol()); handleData->messageCallback = NULL; handleData->messageUserContextCallback = NULL; handleData->lastMessageReceiveTime = INDEFINITE_TIME; /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClient_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/ lowerLayerConfig.upperConfig = config; lowerLayerConfig.waitingToSend = &(handleData->waitingToSend); /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClient_LL_Create shall fail and return NULL.] */ if ((handleData->transportHandle = handleData->IoTHubTransport_Create(&lowerLayerConfig)) == NULL) { LogError("underlying transport failed"); IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); tickcounter_destroy(handleData->tickCounter); free(handleData); result = NULL; } else { IOTHUB_DEVICE_CONFIG deviceConfig; deviceConfig.deviceId = config->deviceId; deviceConfig.deviceKey = config->deviceKey; deviceConfig.deviceSasToken = config->deviceSasToken; /*Codes_SRS_IOTHUBCLIENT_LL_17_008: [IoTHubClient_LL_Create shall call the transport _Register function with a populated structure of type IOTHUB_DEVICE_CONFIG and waitingToSend list.] */ if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(handleData->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_17_009: [If the _Register function fails, this function shall fail and return NULL.]*/ LogError("Registering device in transport failed"); handleData->IoTHubTransport_Destroy(handleData->transportHandle); IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); tickcounter_destroy(handleData->tickCounter); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */ handleData->isSharedTransport = false; /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/ handleData->currentMessageTimeout = 0; result = handleData; } } } } } } return result; }
static PMQTTTRANSPORT_HANDLE_DATA InitializeTransportHandleData(const IOTHUB_CLIENT_CONFIG* upperConfig, PDLIST_ENTRY waitingToSend) { PMQTTTRANSPORT_HANDLE_DATA state = (PMQTTTRANSPORT_HANDLE_DATA)malloc(sizeof(MQTTTRANSPORT_HANDLE_DATA)); if (state == NULL) { LogError("Could not create MQTT transport state. Memory allocation failed.\r\n"); } else if ((state->device_id = STRING_construct(upperConfig->deviceId)) == NULL) { free(state); state = NULL; } else if ((state->device_key = STRING_construct(upperConfig->deviceKey)) == NULL) { LogError("Could not create device key for MQTT\r\n"); STRING_delete(state->device_id); free(state); state = NULL; } else if ( (state->sasTokenSr = ConstructSasToken(upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId) ) == NULL) { LogError("Could not create Sas Token Sr String.\r\n"); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else if ( (state->mqttEventTopic = ConstructEventTopic(upperConfig->deviceId) ) == NULL) { LogError("Could not create mqttEventTopic for MQTT\r\n"); STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else if ((state->mqttMessageTopic = ConstructMessageTopic(upperConfig->deviceId) ) == NULL) { LogError("Could not create mqttMessageTopic for MQTT\r\n"); STRING_delete(state->mqttEventTopic); STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else { state->mqttClient = mqtt_client_init(MqttRecvCallback, MqttOpCompleteCallback, state, defaultPrintLogFunction); if (state->mqttClient == NULL) { STRING_delete(state->mqttEventTopic); STRING_delete(state->mqttMessageTopic); STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [The hostname shall be constructed using the iothubname and iothubSuffix.] */ // TODO: need to strip the ssl or http or tls char tempAddress[DEFAULT_TEMP_STRING_LEN]; (void)snprintf(tempAddress, DEFAULT_TEMP_STRING_LEN, "%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix); if ((state->hostAddress = STRING_construct(tempAddress)) == NULL) { STRING_delete(state->mqttEventTopic); STRING_delete(state->mqttMessageTopic); STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else if ((state->configPassedThroughUsername = buildConfigForUsername(upperConfig)) == NULL) { STRING_delete(state->hostAddress); STRING_delete(state->mqttEventTopic); STRING_delete(state->mqttMessageTopic); STRING_delete(state->sasTokenSr); STRING_delete(state->device_key); STRING_delete(state->device_id); free(state); state = NULL; } else { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [IoTHubTransportMqtt_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */ DList_InitializeListHead(&(state->waitingForAck)); state->destroyCalled = false; state->subscribed = false; state->connected = false; state->packetId = 1; state->llClientHandle = NULL; state->xioTransport = NULL; state->portNum = DEFAULT_PORT_NUMBER; state->waitingToSend = waitingToSend; state->currPacketState = CONNECT_TYPE; } } } return state; }
MQTTAPI_HANDLE MQTTAPI_Create(const MQTTAPI_ConnectOptions* options) { PMQTTTAPI_HANDLE_DATA result; /* Codes_SRS_MQTTAPI_04_011: [If any member of the parameter options is NULL or empty then MQTTAPI_Create shall return NULL.] */ if (options == NULL) { LogError("Invalid Argument. options cannot be NULL.\r\n") result = NULL; } else if (options->deviceId == NULL || strlen(options->deviceId) <= 0) { LogError("Invalid Argument. Device Id cannot be NULL or Empty.\r\n") result = NULL; } else if (options->deviceKey == NULL || strlen(options->deviceKey) <= 0) { LogError("Invalid Argument. Device Key cannot be NULL or Empty.\r\n") result = NULL; } else if (options->serverURI == NULL || strlen(options->serverURI) <= 0) { LogError("Invalid Argument. Device Key cannot be NULL or Empty.\r\n") result = NULL; } else if (options->sasTokenSr == NULL || strlen(options->sasTokenSr) <= 0) { LogError("Invalid Argument. sasTokenSr cannot be NULL or Empty.\r\n") result = NULL; } /* Tests_SRS_MQTTAPI_04_014: [Otherwise, MQTTAPI_Create shall return a MQTTAPI_HANDLE suitable for further calls to the module.] */ else { result = (PMQTTTAPI_HANDLE_DATA)malloc(sizeof(MQTTTAPI_HANDLE_DATA)); if (result != NULL) { result->connected = false; result->subscribed = false; result->dcCallback = NULL; result->maCallBack = NULL; result->maCallbackContext = NULL; result->subscribedTopicHandleData = NULL; result->sasTokenLifetime = SAS_TOKEN_DEFAULT_LIFETIME; result->sasRefreshLine = SAS_TOKEN_DEFAULT_REFRESH_LINE; DList_InitializeListHead(&(result->messagesReceived)); DList_InitializeListHead(&(result->messagesToSend)); DList_InitializeListHead(&(result->messagesSent)); if ((result->LockHandle = Lock_Init()) == NULL) { LogError("Lock_Init failed\r\n"); free(result); result = NULL; } /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ else if ((result->device_id = STRING_construct(options->deviceId)) == NULL) { /* Codes_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ LogError("Could not create deviceId String.\r\n"); Lock_Deinit(result->LockHandle); free(result); result = NULL; } /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ else if ((result->device_key = STRING_construct(options->deviceKey)) == NULL) { /* Codes_SRS_MQTTAPI_04_013: [If saving these parameters fail for any reason MQTTAPI_Create shall return NULL.] */ LogError("Could not create deviceId String.\r\n"); STRING_delete(result->device_id); Lock_Deinit(result->LockHandle); free(result); result = NULL; } /* Codes_SRS_MQTTAPI_04_012: [Parameters deviceId, deviceKey and sasTokenSr shall be saved.] */ else if ((result->sasTokenSr = STRING_construct(options->sasTokenSr)) == NULL) { LogError("Could not create sasTokenSr String.\r\n"); STRING_delete(result->device_key); STRING_delete(result->device_id); Lock_Deinit(result->LockHandle); free(result); result = NULL; } else if (MQTTClient_create(&result->client, options->serverURI, STRING_c_str(result->device_id), MQTTCLIENT_PERSISTENCE_NONE, NULL) != MQTTCLIENT_SUCCESS) { LogError("Could not create MQTT Client.\r\n"); STRING_delete(result->sasTokenSr); STRING_delete(result->device_key); STRING_delete(result->device_id); Lock_Deinit(result->LockHandle); free(result); result = NULL; } /* Codes_SRS_MQTTAPI_04_004: [This function is registered when the user makes a call to MQTTAPI_SetCallbacks.] */ /* Codes_SRS_MQTTAPI_04_005: [The context parameter is a pointer to the original value passed by MQTTAPI_SetCallbacks, which contains application-specific context.] */ /* Codes_SRS_MQTTAPI_04_008: [This function is registered when the user makes a call to MQTTAPI_SetCallbacks.] */ else if (MQTTClient_setCallbacks(result->client, result, connectionLost, msgarrvd, delivered) != MQTTCLIENT_SUCCESS) { LogError("Could not set callbacks.\r\n"); STRING_delete(result->sasTokenSr); STRING_delete(result->device_key); STRING_delete(result->device_id); MQTTClient_destroy(&result->client); Lock_Deinit(result->LockHandle); free(result); result = NULL; } /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ /* Codes_SRS_MQTTAPI_04_047: [Otherwise MQTTAPI_Create shall return a non-NULL MQTTAPI_HANDLE] */ else if (!checkAndTryToConnect(result)) { /* Codes_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ LogError("Could not Connect to MQTT Server.\r\n"); STRING_delete(result->sasTokenSr); STRING_delete(result->device_key); STRING_delete(result->device_id); MQTTClient_destroy(&result->client); Lock_Deinit(result->LockHandle); free(result); result = NULL; } } else { /* Codes_SRS_MQTTAPI_04_015: [If creating instance fails for any reason, then MQTTAPI_Create shall return NULL.] */ LogError("Could not create MQTT API handle data. Memory allocation failed.\r\n"); result = NULL; } } return (MQTTAPI_HANDLE)result; }
IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config) { IOTHUB_CLIENT_LL_HANDLE result; /*Codes_SRS_IOTHUBCLIENT_LL_17_001: [IoTHubClient_LL_CreateWithTransport shall return NULL if config parameter is NULL, or protocol field is NULL or transportHandle is NULL.]*/ if ( (config == NULL) || (config->protocol == NULL) || (config->transportHandle == NULL) || /*Codes_SRS_IOTHUBCLIENT_LL_02_098: [ IoTHubClient_LL_CreateWithTransport shall fail and return NULL if both config->deviceKey AND config->deviceSasToken are NULL. ]*/ ((config->deviceKey == NULL) && (config->deviceSasToken == NULL)) ) { result = NULL; LogError("invalid configuration (NULL detected)"); } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_002: [IoTHubClient_LL_CreateWithTransport shall allocate data for the IOTHUB_CLIENT_LL_HANDLE.]*/ IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); if (handleData == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_17_003: [If allocation fails, the function shall fail and return NULL.] */ LogError("malloc failed"); result = NULL; } else { handleData->transportHandle = config->transportHandle; setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol()); #ifndef DONT_USE_UPLOADTOBLOB const char* hostname = STRING_c_str(handleData->IoTHubTransport_GetHostname(handleData->transportHandle)); /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ /*the first '.' says where the iothubname finishes*/ const char* whereIsDot = strchr(hostname, '.'); if (whereIsDot == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ LogError("unable to determine the IoTHub name"); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ char* IoTHubName = malloc(whereIsDot - hostname + 1); if (IoTHubName == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ LogError("unable to malloc"); free(handleData); result = NULL; } else { const char* IotHubSuffix = whereIsDot + 1; memcpy(IoTHubName, hostname, whereIsDot - hostname); IoTHubName[whereIsDot - hostname ] = '\0'; IOTHUB_CLIENT_CONFIG temp; temp.deviceId = config->deviceId; temp.deviceKey = config->deviceKey; temp.deviceSasToken = config->deviceSasToken; temp.iotHubName = IoTHubName; temp.iotHubSuffix = IotHubSuffix; temp.protocol = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/ temp.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/ /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(&temp); if (handleData->uploadToBlobHandle == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ LogError("unable to IoTHubClient_LL_UploadToBlob_Create"); free(handleData); result = NULL; } else #endif { /*Codes_SRS_IOTHUBCLIENT_LL_02_047: [ IoTHubClient_LL_CreateWithTransport shall create a TICK_COUNTER_HANDLE. ]*/ if ((handleData->tickCounter = tickcounter_create()) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_02_048: [ If creating the handle fails, then IoTHubClient_LL_CreateWithTransport shall fail and return NULL ]*/ LogError("unable to get a tickcounter"); #ifndef DONT_USE_UPLOADTOBLOB IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); #endif free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_004: [IoTHubClient_LL_CreateWithTransport shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ DList_InitializeListHead(&(handleData->waitingToSend)); handleData->messageCallback = NULL; handleData->messageUserContextCallback = NULL; handleData->lastMessageReceiveTime = INDEFINITE_TIME; IOTHUB_DEVICE_CONFIG deviceConfig; deviceConfig.deviceId = config->deviceId; deviceConfig.deviceKey = config->deviceKey; deviceConfig.deviceSasToken = config->deviceSasToken; /*Codes_SRS_IOTHUBCLIENT_LL_17_006: [IoTHubClient_LL_CreateWithTransport shall call the transport _Register function with the IOTHUB_DEVICE_CONFIG populated structure and waitingToSend list.]*/ if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(config->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL) { /*Codes_SRS_IOTHUBCLIENT_LL_17_007: [If the _Register function fails, this function shall fail and return NULL.]*/ LogError("Registering device in transport failed"); #ifndef DONT_USE_UPLOADTOBLOB IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); #endif tickcounter_destroy(handleData->tickCounter); free(handleData); result = NULL; } else { /*Codes_SRS_IOTHUBCLIENT_LL_17_005: [IoTHubClient_LL_CreateWithTransport shall save the transport handle and mark this transport as shared.]*/ handleData->isSharedTransport = true; /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/ handleData->currentMessageTimeout = 0; result = handleData; } } } #ifndef DONT_USE_UPLOADTOBLOB free(IoTHubName); } } #endif } } return result; }