A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Mar 24 16:35:45 2017 -0700
Revision:
21:f9c433d8e6ca
Parent:
19:000ab4e6a2c1
Child:
22:524bded3f7a8
1.1.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
AzureIoTClient 6:641a9672db08 5 #include <stdbool.h>
Azure.IoT Build 0:6ae2f7bca550 6 #include <stdio.h>
Azure.IoT Build 0:6ae2f7bca550 7 #include <string.h>
AzureIoTClient 19:000ab4e6a2c1 8 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 21:f9c433d8e6ca 9 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 21:f9c433d8e6ca 10 #include "azure_c_shared_utility/singlylinkedlist.h"
Azure.IoT Build 0:6ae2f7bca550 11 #include "azure_uamqp_c/cbs.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/amqp_management.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/session.h"
Azure.IoT Build 0:6ae2f7bca550 14
AzureIoTClient 21:f9c433d8e6ca 15 typedef enum CBS_STATE_TAG
AzureIoTClient 21:f9c433d8e6ca 16 {
AzureIoTClient 21:f9c433d8e6ca 17 CBS_STATE_CLOSED,
AzureIoTClient 21:f9c433d8e6ca 18 CBS_STATE_OPENING,
AzureIoTClient 21:f9c433d8e6ca 19 CBS_STATE_OPEN,
AzureIoTClient 21:f9c433d8e6ca 20 CBS_STATE_ERROR
AzureIoTClient 21:f9c433d8e6ca 21 } CBS_STATE;
AzureIoTClient 21:f9c433d8e6ca 22
AzureIoTClient 21:f9c433d8e6ca 23 typedef struct CBS_OPERATION_TAG
AzureIoTClient 21:f9c433d8e6ca 24 {
AzureIoTClient 21:f9c433d8e6ca 25 ON_CBS_OPERATION_COMPLETE on_cbs_operation_complete;
AzureIoTClient 21:f9c433d8e6ca 26 void* on_cbs_operation_complete_context;
AzureIoTClient 21:f9c433d8e6ca 27 SINGLYLINKEDLIST_HANDLE pending_operations;
AzureIoTClient 21:f9c433d8e6ca 28 } CBS_OPERATION;
AzureIoTClient 21:f9c433d8e6ca 29
Azure.IoT Build 0:6ae2f7bca550 30 typedef struct CBS_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 31 {
AzureIoTClient 6:641a9672db08 32 AMQP_MANAGEMENT_HANDLE amqp_management;
AzureIoTClient 21:f9c433d8e6ca 33 CBS_STATE cbs_state;
AzureIoTClient 21:f9c433d8e6ca 34 ON_CBS_OPEN_COMPLETE on_cbs_open_complete;
AzureIoTClient 21:f9c433d8e6ca 35 void* on_cbs_open_complete_context;
AzureIoTClient 21:f9c433d8e6ca 36 ON_CBS_ERROR on_cbs_error;
AzureIoTClient 21:f9c433d8e6ca 37 void* on_cbs_error_context;
AzureIoTClient 21:f9c433d8e6ca 38 SINGLYLINKEDLIST_HANDLE pending_operations;
Azure.IoT Build 0:6ae2f7bca550 39 } CBS_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 40
Azure.IoT Build 0:6ae2f7bca550 41 static int add_string_key_value_pair_to_map(AMQP_VALUE map, const char* key, const char* value)
Azure.IoT Build 0:6ae2f7bca550 42 {
AzureIoTClient 6:641a9672db08 43 int result;
Azure.IoT Build 0:6ae2f7bca550 44
AzureIoTClient 6:641a9672db08 45 AMQP_VALUE key_value = amqpvalue_create_string(key);
AzureIoTClient 21:f9c433d8e6ca 46 if (key_value == NULL)
AzureIoTClient 6:641a9672db08 47 {
AzureIoTClient 21:f9c433d8e6ca 48 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 49 LogError("Failed creating value for property key %s", key);
AzureIoTClient 19:000ab4e6a2c1 50 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 51 }
AzureIoTClient 6:641a9672db08 52 else
AzureIoTClient 6:641a9672db08 53 {
AzureIoTClient 6:641a9672db08 54 AMQP_VALUE value_value = amqpvalue_create_string(value);
AzureIoTClient 6:641a9672db08 55 if (value_value == NULL)
AzureIoTClient 6:641a9672db08 56 {
AzureIoTClient 21:f9c433d8e6ca 57 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 58 LogError("Failed creating value for property value %s", value);
AzureIoTClient 19:000ab4e6a2c1 59 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 60 }
AzureIoTClient 6:641a9672db08 61 else
AzureIoTClient 6:641a9672db08 62 {
AzureIoTClient 6:641a9672db08 63 if (amqpvalue_set_map_value(map, key_value, value_value) != 0)
AzureIoTClient 6:641a9672db08 64 {
AzureIoTClient 21:f9c433d8e6ca 65 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 66 LogError("Failed inserting key/value pair in the map");
AzureIoTClient 19:000ab4e6a2c1 67 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 68 }
AzureIoTClient 6:641a9672db08 69 else
AzureIoTClient 6:641a9672db08 70 {
AzureIoTClient 6:641a9672db08 71 result = 0;
AzureIoTClient 6:641a9672db08 72 }
Azure.IoT Build 0:6ae2f7bca550 73
AzureIoTClient 21:f9c433d8e6ca 74 amqpvalue_destroy(value_value);
AzureIoTClient 6:641a9672db08 75 }
Azure.IoT Build 0:6ae2f7bca550 76
AzureIoTClient 21:f9c433d8e6ca 77 amqpvalue_destroy(key_value);
AzureIoTClient 6:641a9672db08 78 }
Azure.IoT Build 0:6ae2f7bca550 79
AzureIoTClient 6:641a9672db08 80 return result;
Azure.IoT Build 0:6ae2f7bca550 81 }
Azure.IoT Build 0:6ae2f7bca550 82
AzureIoTClient 21:f9c433d8e6ca 83 static void on_underlying_amqp_management_state_changed(void* context, AMQP_MANAGEMENT_STATE new_amqp_management_state, AMQP_MANAGEMENT_STATE previous_amqp_management_state)
Azure.IoT Build 0:6ae2f7bca550 84 {
AzureIoTClient 21:f9c433d8e6ca 85 if (context == NULL)
AzureIoTClient 6:641a9672db08 86 {
AzureIoTClient 21:f9c433d8e6ca 87 /* Codes_SRS_CBS_01_068: [ When `on_amqp_management_state_changed` is called with NULL `context`, it shall do nothing. ]*/
AzureIoTClient 21:f9c433d8e6ca 88 LogError("on_underlying_amqp_management_state_changed called with NULL context");
AzureIoTClient 6:641a9672db08 89 }
AzureIoTClient 6:641a9672db08 90 else
AzureIoTClient 6:641a9672db08 91 {
AzureIoTClient 21:f9c433d8e6ca 92 CBS_HANDLE cbs = (CBS_HANDLE)context;
AzureIoTClient 21:f9c433d8e6ca 93
AzureIoTClient 21:f9c433d8e6ca 94 /* Codes_SRS_CBS_01_069: [ If there is a transition detected to a new state the following shall be performed: ]*/
AzureIoTClient 21:f9c433d8e6ca 95 if (new_amqp_management_state != previous_amqp_management_state)
AzureIoTClient 6:641a9672db08 96 {
AzureIoTClient 21:f9c433d8e6ca 97 switch (cbs->cbs_state)
AzureIoTClient 21:f9c433d8e6ca 98 {
AzureIoTClient 21:f9c433d8e6ca 99 default:
AzureIoTClient 21:f9c433d8e6ca 100 LogError("AMQP management state transition while CBS instance is in unknown state");
AzureIoTClient 21:f9c433d8e6ca 101 break;
AzureIoTClient 21:f9c433d8e6ca 102
AzureIoTClient 21:f9c433d8e6ca 103 case CBS_STATE_CLOSED:
AzureIoTClient 21:f9c433d8e6ca 104 LogError("AMQP management state transition while CBS instance is CLOSED");
AzureIoTClient 21:f9c433d8e6ca 105 break;
AzureIoTClient 21:f9c433d8e6ca 106
AzureIoTClient 21:f9c433d8e6ca 107 case CBS_STATE_ERROR:
AzureIoTClient 21:f9c433d8e6ca 108 {
AzureIoTClient 21:f9c433d8e6ca 109 LogError("AMQP management state transition while CBS instance is in ERROR");
AzureIoTClient 21:f9c433d8e6ca 110 break;
AzureIoTClient 21:f9c433d8e6ca 111 }
AzureIoTClient 21:f9c433d8e6ca 112 case CBS_STATE_OPENING:
AzureIoTClient 21:f9c433d8e6ca 113 {
AzureIoTClient 21:f9c433d8e6ca 114 switch (new_amqp_management_state)
AzureIoTClient 21:f9c433d8e6ca 115 {
AzureIoTClient 21:f9c433d8e6ca 116 default:
AzureIoTClient 21:f9c433d8e6ca 117 LogError("Unknown AMQP management state");
AzureIoTClient 21:f9c433d8e6ca 118 case AMQP_MANAGEMENT_STATE_ERROR:
AzureIoTClient 21:f9c433d8e6ca 119 /* Codes_SRS_CBS_01_073: [ If CBS is opening and the new state is not `AMQP_MANAGEMENT_STATE_OPEN` the callback `on_cbs_open_complete` shall be called with `CBS_OPEN_ERROR` and the `on_cbs_open_complete_context` shall be passed as argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 120 cbs->cbs_state = CBS_STATE_CLOSED;
AzureIoTClient 21:f9c433d8e6ca 121 cbs->on_cbs_open_complete(cbs->on_cbs_open_complete_context, CBS_OPEN_ERROR);
AzureIoTClient 21:f9c433d8e6ca 122 break;
AzureIoTClient 21:f9c433d8e6ca 123
AzureIoTClient 21:f9c433d8e6ca 124 case AMQP_MANAGEMENT_STATE_OPENING:
AzureIoTClient 21:f9c433d8e6ca 125 /* do nothing */
AzureIoTClient 21:f9c433d8e6ca 126 break;
AzureIoTClient 21:f9c433d8e6ca 127
AzureIoTClient 21:f9c433d8e6ca 128 case AMQP_MANAGEMENT_STATE_OPEN:
AzureIoTClient 21:f9c433d8e6ca 129 /* Codes_SRS_CBS_01_070: [ If CBS is opening and the new state is `AMQP_MANAGEMENT_STATE_OPEN` the callback `on_cbs_open_complete` shall be called with `CBS_OPEN_OK` and the `on_cbs_open_complete_context` shall be passed as argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 130 cbs->cbs_state = CBS_STATE_OPEN;
AzureIoTClient 21:f9c433d8e6ca 131 cbs->on_cbs_open_complete(cbs->on_cbs_open_complete_context, CBS_OPEN_OK);
AzureIoTClient 21:f9c433d8e6ca 132 break;
AzureIoTClient 21:f9c433d8e6ca 133 }
AzureIoTClient 21:f9c433d8e6ca 134 break;
AzureIoTClient 21:f9c433d8e6ca 135 }
AzureIoTClient 21:f9c433d8e6ca 136 case CBS_STATE_OPEN:
AzureIoTClient 21:f9c433d8e6ca 137 {
AzureIoTClient 21:f9c433d8e6ca 138 switch (new_amqp_management_state)
AzureIoTClient 21:f9c433d8e6ca 139 {
AzureIoTClient 21:f9c433d8e6ca 140 default:
AzureIoTClient 21:f9c433d8e6ca 141 LogError("Unknown AMQP management state");
AzureIoTClient 21:f9c433d8e6ca 142 /* Codes_SRS_CBS_01_074: [ If CBS is open and the new state is not `AMQP_MANAGEMENT_STATE_OPEN` the callback `on_cbs_error` shall be called and the `on_cbs_error_context` shall be passed as argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 143 case AMQP_MANAGEMENT_STATE_ERROR:
AzureIoTClient 21:f9c433d8e6ca 144 case AMQP_MANAGEMENT_STATE_OPENING:
AzureIoTClient 21:f9c433d8e6ca 145 cbs->cbs_state = CBS_STATE_ERROR;
AzureIoTClient 21:f9c433d8e6ca 146 cbs->on_cbs_error(cbs->on_cbs_error_context);
AzureIoTClient 21:f9c433d8e6ca 147 break;
AzureIoTClient 21:f9c433d8e6ca 148
AzureIoTClient 21:f9c433d8e6ca 149 case AMQP_MANAGEMENT_STATE_OPEN:
AzureIoTClient 21:f9c433d8e6ca 150 LogError("Unexpected transition to OPEN while CBS is already OPEN");
AzureIoTClient 21:f9c433d8e6ca 151 break;
AzureIoTClient 21:f9c433d8e6ca 152 }
AzureIoTClient 21:f9c433d8e6ca 153 break;
AzureIoTClient 21:f9c433d8e6ca 154 }
AzureIoTClient 21:f9c433d8e6ca 155 }
AzureIoTClient 21:f9c433d8e6ca 156 }
AzureIoTClient 21:f9c433d8e6ca 157 }
AzureIoTClient 21:f9c433d8e6ca 158 }
AzureIoTClient 21:f9c433d8e6ca 159
AzureIoTClient 21:f9c433d8e6ca 160 static void on_amqp_management_operation_complete(void* context, OPERATION_RESULT operation_result, unsigned int status_code, const char* status_description)
AzureIoTClient 21:f9c433d8e6ca 161 {
AzureIoTClient 21:f9c433d8e6ca 162 if (context == NULL)
AzureIoTClient 21:f9c433d8e6ca 163 {
AzureIoTClient 21:f9c433d8e6ca 164 /* Codes_SRS_CBS_01_091: [ When `on_amqp_management_operation_complete` is called with a NULL context it shall do nothing. ]*/
AzureIoTClient 21:f9c433d8e6ca 165 LogError("on_amqp_management_operation_complete called with NULL context");
AzureIoTClient 21:f9c433d8e6ca 166 }
AzureIoTClient 21:f9c433d8e6ca 167 else
AzureIoTClient 21:f9c433d8e6ca 168 {
AzureIoTClient 21:f9c433d8e6ca 169 /* Codes_SRS_CBS_01_103: [ The `context` shall be used to obtain the pending operation information stored in the pending operations linked list by calling `singlylinkedlist_item_get_value`. ]*/
AzureIoTClient 21:f9c433d8e6ca 170 CBS_OPERATION* cbs_operation = (CBS_OPERATION*)singlylinkedlist_item_get_value((LIST_ITEM_HANDLE)context);
AzureIoTClient 21:f9c433d8e6ca 171 CBS_OPERATION_RESULT cbs_operation_result;
AzureIoTClient 21:f9c433d8e6ca 172
AzureIoTClient 21:f9c433d8e6ca 173 if (cbs_operation == NULL)
AzureIoTClient 21:f9c433d8e6ca 174 {
AzureIoTClient 21:f9c433d8e6ca 175 LogError("NULL cbs_operation");
AzureIoTClient 6:641a9672db08 176 }
AzureIoTClient 6:641a9672db08 177 else
AzureIoTClient 6:641a9672db08 178 {
AzureIoTClient 21:f9c433d8e6ca 179 switch (operation_result)
AzureIoTClient 6:641a9672db08 180 {
AzureIoTClient 21:f9c433d8e6ca 181 default:
AzureIoTClient 21:f9c433d8e6ca 182 cbs_operation_result = CBS_OPERATION_RESULT_CBS_ERROR;
AzureIoTClient 21:f9c433d8e6ca 183 break;
AzureIoTClient 21:f9c433d8e6ca 184
AzureIoTClient 21:f9c433d8e6ca 185 case OPERATION_RESULT_OPERATION_FAILED:
AzureIoTClient 21:f9c433d8e6ca 186 /* Tests_SRS_CBS_01_094: [ When `on_amqp_management_operation_complete` is called with `OPERATION_RESULT_OPERATION_FAILED`, the associated cbs operation complete callback shall be called with `CBS_OPERATION_RESULT_OPERATION_FAILED` and passing the `on_cbs_put_token_complete_context` as the context argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 187 cbs_operation_result = CBS_OPERATION_RESULT_OPERATION_FAILED;
AzureIoTClient 21:f9c433d8e6ca 188 break;
AzureIoTClient 21:f9c433d8e6ca 189
AzureIoTClient 21:f9c433d8e6ca 190 case OPERATION_RESULT_ERROR:
AzureIoTClient 21:f9c433d8e6ca 191 /* Tests_SRS_CBS_01_093: [ When `on_amqp_management_operation_complete` is called with `OPERATION_RESULT_ERROR`, the associated cbs operation complete callback shall be called with `CBS_OPERATION_RESULT_CBS_ERROR` and passing the `on_cbs_put_token_complete_context` as the context argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 192 cbs_operation_result = CBS_OPERATION_RESULT_CBS_ERROR;
AzureIoTClient 21:f9c433d8e6ca 193 break;
AzureIoTClient 21:f9c433d8e6ca 194
AzureIoTClient 21:f9c433d8e6ca 195 case OPERATION_RESULT_OK:
AzureIoTClient 21:f9c433d8e6ca 196 /* Codes_SRS_CBS_01_092: [ When `on_amqp_management_operation_complete` is called with `OPERATION_RESULT_OK`, the associated cbs operation complete callback shall be called with `CBS_OPERATION_RESULT_OK` and passing the `on_cbs_put_token_complete_context` as the context argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 197 cbs_operation_result = CBS_OPERATION_RESULT_OK;
AzureIoTClient 21:f9c433d8e6ca 198 break;
AzureIoTClient 6:641a9672db08 199 }
Azure.IoT Build 0:6ae2f7bca550 200
AzureIoTClient 21:f9c433d8e6ca 201 /* Codes_SRS_CBS_01_095: [ `status_code` and `status_description` shall be passed as they are to the cbs operation complete callback. ]*/
AzureIoTClient 21:f9c433d8e6ca 202 /* Codes_SRS_CBS_01_014: [ The response message has the following application-properties: ]*/
AzureIoTClient 21:f9c433d8e6ca 203 /* Codes_SRS_CBS_01_013: [ status-code No int HTTP response code [RFC2616]. ]*/
AzureIoTClient 21:f9c433d8e6ca 204 /* Codes_SRS_CBS_01_015: [ status-description Yes string Description of the status. ]*/
AzureIoTClient 21:f9c433d8e6ca 205 /* Codes_SRS_CBS_01_016: [ The body of the message MUST be empty. ]*/
AzureIoTClient 21:f9c433d8e6ca 206 /* Codes_SRS_CBS_01_026: [ The response message has the following application-properties: ]*/
AzureIoTClient 21:f9c433d8e6ca 207 /* Codes_SRS_CBS_01_027: [ status-code Yes int HTTP response code [RFC2616]. ]*/
AzureIoTClient 21:f9c433d8e6ca 208 /* Codes_SRS_CBS_01_028: [ status-description No string Description of the status. ]*/
AzureIoTClient 21:f9c433d8e6ca 209 /* Codes_SRS_CBS_01_029: [ The body of the message MUST be empty. ]*/
AzureIoTClient 21:f9c433d8e6ca 210 cbs_operation->on_cbs_operation_complete(cbs_operation->on_cbs_operation_complete_context, cbs_operation_result, status_code, status_description);
Azure.IoT Build 0:6ae2f7bca550 211
AzureIoTClient 21:f9c433d8e6ca 212 /* Codes_SRS_CBS_01_102: [ The pending operation shall be removed from the pending operations list by calling `singlylinkedlist_remove`. ]*/
AzureIoTClient 21:f9c433d8e6ca 213 if (singlylinkedlist_remove(cbs_operation->pending_operations, (LIST_ITEM_HANDLE)context) != 0)
AzureIoTClient 6:641a9672db08 214 {
AzureIoTClient 21:f9c433d8e6ca 215 LogError("Failed removing operation from the pending list");
AzureIoTClient 6:641a9672db08 216 }
Azure.IoT Build 0:6ae2f7bca550 217
AzureIoTClient 21:f9c433d8e6ca 218 /* Codes_SRS_CBS_01_096: [ The `context` for the operation shall also be freed. ]*/
AzureIoTClient 21:f9c433d8e6ca 219 free(cbs_operation);
AzureIoTClient 6:641a9672db08 220 }
AzureIoTClient 6:641a9672db08 221 }
Azure.IoT Build 0:6ae2f7bca550 222 }
Azure.IoT Build 0:6ae2f7bca550 223
AzureIoTClient 21:f9c433d8e6ca 224 CBS_HANDLE cbs_create(SESSION_HANDLE session)
Azure.IoT Build 0:6ae2f7bca550 225 {
AzureIoTClient 6:641a9672db08 226 CBS_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 227
AzureIoTClient 6:641a9672db08 228 if (session == NULL)
AzureIoTClient 6:641a9672db08 229 {
AzureIoTClient 21:f9c433d8e6ca 230 /* Codes_SRS_CBS_01_033: [** If `session` is NULL then `cbs_create` shall fail and return NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 231 LogError("NULL session handle");
AzureIoTClient 6:641a9672db08 232 result = NULL;
AzureIoTClient 6:641a9672db08 233 }
AzureIoTClient 6:641a9672db08 234 else
AzureIoTClient 6:641a9672db08 235 {
AzureIoTClient 21:f9c433d8e6ca 236 result = (CBS_INSTANCE*)malloc(sizeof(CBS_INSTANCE));
AzureIoTClient 21:f9c433d8e6ca 237 if (result == NULL)
AzureIoTClient 21:f9c433d8e6ca 238 {
AzureIoTClient 21:f9c433d8e6ca 239 /* Codes_SRS_CBS_01_076: [ If allocating memory for the new handle fails, `cbs_create` shall fail and return NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 240 LogError("Cannot allocate memory for cbs instance.");
AzureIoTClient 21:f9c433d8e6ca 241 }
AzureIoTClient 21:f9c433d8e6ca 242 else
AzureIoTClient 6:641a9672db08 243 {
AzureIoTClient 21:f9c433d8e6ca 244 /* Codes_SRS_CBS_01_097: [ `cbs_create` shall create a singly linked list for pending operations by calling `singlylinkedlist_create`. ]*/
AzureIoTClient 21:f9c433d8e6ca 245 result->pending_operations = singlylinkedlist_create();
AzureIoTClient 21:f9c433d8e6ca 246 if (result->pending_operations == NULL)
AzureIoTClient 21:f9c433d8e6ca 247 {
AzureIoTClient 21:f9c433d8e6ca 248 /* Codes_SRS_CBS_01_101: [ If `singlylinkedlist_create` fails, `cbs_create` shall fail and return NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 249 LogError("Cannot allocate pending operations list.");
AzureIoTClient 21:f9c433d8e6ca 250 free(result);
AzureIoTClient 21:f9c433d8e6ca 251 result = NULL;
AzureIoTClient 21:f9c433d8e6ca 252 }
AzureIoTClient 21:f9c433d8e6ca 253 else
AzureIoTClient 6:641a9672db08 254 {
AzureIoTClient 21:f9c433d8e6ca 255 /* Codes_SRS_CBS_01_034: [ `cbs_create` shall create an AMQP management handle by calling `amqpmanagement_create`. ]*/
AzureIoTClient 21:f9c433d8e6ca 256 /* Codes_SRS_CBS_01_002: [ Tokens are communicated between AMQP peers by sending specially-formatted AMQP messages to the Claims-based Security Node. ]*/
AzureIoTClient 21:f9c433d8e6ca 257 /* Codes_SRS_CBS_01_003: [ The mechanism follows the scheme defined in the AMQP Management specification [AMQPMAN]. ]*/
AzureIoTClient 21:f9c433d8e6ca 258 result->amqp_management = amqpmanagement_create(session, "$cbs", on_underlying_amqp_management_state_changed, result);
AzureIoTClient 21:f9c433d8e6ca 259 if (result->amqp_management == NULL)
AzureIoTClient 21:f9c433d8e6ca 260 {
AzureIoTClient 21:f9c433d8e6ca 261 free(result);
AzureIoTClient 21:f9c433d8e6ca 262 result = NULL;
AzureIoTClient 21:f9c433d8e6ca 263 }
AzureIoTClient 21:f9c433d8e6ca 264 else
AzureIoTClient 21:f9c433d8e6ca 265 {
AzureIoTClient 21:f9c433d8e6ca 266 result->cbs_state = CBS_STATE_CLOSED;
AzureIoTClient 21:f9c433d8e6ca 267 }
AzureIoTClient 6:641a9672db08 268 }
AzureIoTClient 6:641a9672db08 269 }
AzureIoTClient 6:641a9672db08 270 }
AzureIoTClient 21:f9c433d8e6ca 271
AzureIoTClient 21:f9c433d8e6ca 272 /* Codes_SRS_CBS_01_001: [ `cbs_create` shall create a new CBS instance and on success return a non-NULL handle to it. ]*/
AzureIoTClient 6:641a9672db08 273 return result;
Azure.IoT Build 0:6ae2f7bca550 274 }
Azure.IoT Build 0:6ae2f7bca550 275
Azure.IoT Build 0:6ae2f7bca550 276 void cbs_destroy(CBS_HANDLE cbs)
Azure.IoT Build 0:6ae2f7bca550 277 {
AzureIoTClient 21:f9c433d8e6ca 278 if (cbs == NULL)
AzureIoTClient 21:f9c433d8e6ca 279 {
AzureIoTClient 21:f9c433d8e6ca 280 /* Codes_SRS_CBS_01_037: [ If `cbs` is NULL, `cbs_destroy` shall do nothing. ]*/
AzureIoTClient 21:f9c433d8e6ca 281 LogError("NULL cbs handle");
AzureIoTClient 21:f9c433d8e6ca 282 }
AzureIoTClient 21:f9c433d8e6ca 283 else
AzureIoTClient 6:641a9672db08 284 {
AzureIoTClient 21:f9c433d8e6ca 285 LIST_ITEM_HANDLE first_pending_operation;
AzureIoTClient 21:f9c433d8e6ca 286
AzureIoTClient 21:f9c433d8e6ca 287 /* Codes_SRS_CBS_01_100: [ If the CBS instance is not closed, all actions performed by `cbs_close` shall be performed. ]*/
AzureIoTClient 21:f9c433d8e6ca 288 if (cbs->cbs_state != CBS_STATE_CLOSED)
AzureIoTClient 21:f9c433d8e6ca 289 {
AzureIoTClient 21:f9c433d8e6ca 290 (void)amqpmanagement_close(cbs->amqp_management);
AzureIoTClient 21:f9c433d8e6ca 291 }
AzureIoTClient 21:f9c433d8e6ca 292
AzureIoTClient 21:f9c433d8e6ca 293 /* Codes_SRS_CBS_01_036: [ `cbs_destroy` shall free all resources associated with the handle `cbs`. ]*/
AzureIoTClient 21:f9c433d8e6ca 294 /* Codes_SRS_CBS_01_038: [ `cbs_destroy` shall free the AMQP management handle created in `cbs_create` by calling `amqpmanagement_destroy`. ]*/
AzureIoTClient 6:641a9672db08 295 amqpmanagement_destroy(cbs->amqp_management);
AzureIoTClient 21:f9c433d8e6ca 296
AzureIoTClient 21:f9c433d8e6ca 297 /* Codes_SRS_CBS_01_099: [ All pending operations shall be freed. ]*/
AzureIoTClient 21:f9c433d8e6ca 298 while ((first_pending_operation = singlylinkedlist_get_head_item(cbs->pending_operations)) != NULL)
AzureIoTClient 21:f9c433d8e6ca 299 {
AzureIoTClient 21:f9c433d8e6ca 300 CBS_OPERATION* pending_operation = (CBS_OPERATION*)singlylinkedlist_item_get_value(first_pending_operation);
AzureIoTClient 21:f9c433d8e6ca 301 if (pending_operation != NULL)
AzureIoTClient 21:f9c433d8e6ca 302 {
AzureIoTClient 21:f9c433d8e6ca 303 pending_operation->on_cbs_operation_complete(pending_operation->on_cbs_operation_complete_context, CBS_OPERATION_RESULT_BECAUSE_DESTROY, 0, NULL);
AzureIoTClient 21:f9c433d8e6ca 304 free(pending_operation);
AzureIoTClient 21:f9c433d8e6ca 305 }
AzureIoTClient 21:f9c433d8e6ca 306
AzureIoTClient 21:f9c433d8e6ca 307 singlylinkedlist_remove(cbs->pending_operations, first_pending_operation);
AzureIoTClient 21:f9c433d8e6ca 308 }
AzureIoTClient 21:f9c433d8e6ca 309
AzureIoTClient 21:f9c433d8e6ca 310 /* Codes_SRS_CBS_01_098: [ `cbs_destroy` shall free the pending operations list by calling `singlylinkedlist_destroy`. ]*/
AzureIoTClient 21:f9c433d8e6ca 311 singlylinkedlist_destroy(cbs->pending_operations);
AzureIoTClient 21:f9c433d8e6ca 312 free(cbs);
AzureIoTClient 6:641a9672db08 313 }
Azure.IoT Build 0:6ae2f7bca550 314 }
Azure.IoT Build 0:6ae2f7bca550 315
AzureIoTClient 21:f9c433d8e6ca 316 int cbs_open_async(CBS_HANDLE cbs, ON_CBS_OPEN_COMPLETE on_cbs_open_complete, void* on_cbs_open_complete_context, ON_CBS_ERROR on_cbs_error, void* on_cbs_error_context)
Azure.IoT Build 0:6ae2f7bca550 317 {
AzureIoTClient 6:641a9672db08 318 int result;
Azure.IoT Build 0:6ae2f7bca550 319
AzureIoTClient 21:f9c433d8e6ca 320 /* Codes_SRS_CBS_01_042: [ `on_cbs_open_complete_context` and `on_cbs_error_context` shall be allowed to be NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 321 if ((cbs == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 322 (on_cbs_open_complete == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 323 (on_cbs_error == NULL))
AzureIoTClient 6:641a9672db08 324 {
AzureIoTClient 21:f9c433d8e6ca 325 /* Codes_SRS_CBS_01_040: [ If any of the arguments `cbs`, `on_cbs_open_complete` or `on_cbs_error` is NULL, then `cbs_open_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 326 LogError("Bad arguments: cbs = %p, on_cbs_open_complete = %p, on_cbs_error = %p",
AzureIoTClient 21:f9c433d8e6ca 327 cbs, on_cbs_open_complete, on_cbs_error);
AzureIoTClient 21:f9c433d8e6ca 328 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 329 }
AzureIoTClient 21:f9c433d8e6ca 330 else if (cbs->cbs_state != CBS_STATE_CLOSED)
AzureIoTClient 21:f9c433d8e6ca 331 {
AzureIoTClient 21:f9c433d8e6ca 332 /* Codes_SRS_CBS_01_043: [ `cbs_open_async` while already open or opening shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 333 LogError("cbs instance already open");
AzureIoTClient 19:000ab4e6a2c1 334 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 335 }
AzureIoTClient 6:641a9672db08 336 else
AzureIoTClient 6:641a9672db08 337 {
AzureIoTClient 21:f9c433d8e6ca 338 /* Codes_SRS_CBS_01_078: [ The cbs instance shall be considered OPENING until the `on_amqp_management_state_changed` is called by the AMQP management instance indicating that the open has completed (succesfull or not). ]*/
AzureIoTClient 21:f9c433d8e6ca 339 cbs->cbs_state = CBS_STATE_OPENING;
AzureIoTClient 21:f9c433d8e6ca 340 cbs->on_cbs_open_complete = on_cbs_open_complete;
AzureIoTClient 21:f9c433d8e6ca 341 cbs->on_cbs_open_complete_context = on_cbs_open_complete_context;
AzureIoTClient 21:f9c433d8e6ca 342 cbs->on_cbs_error = on_cbs_error;
AzureIoTClient 21:f9c433d8e6ca 343 cbs->on_cbs_error_context = on_cbs_error_context;
AzureIoTClient 21:f9c433d8e6ca 344
AzureIoTClient 21:f9c433d8e6ca 345 /* Codes_SRS_CBS_01_039: [ `cbs_open_async` shall open the cbs communication by calling `amqpmanagement_open` on the AMQP management handle created in `cbs_create`. ]*/
AzureIoTClient 6:641a9672db08 346 if (amqpmanagement_open(cbs->amqp_management) != 0)
AzureIoTClient 6:641a9672db08 347 {
AzureIoTClient 21:f9c433d8e6ca 348 /* Codes_SRS_CBS_01_041: [ If `amqpmanagement_open` fails, shall fail and return a non-zero value. ]*/
AzureIoTClient 19:000ab4e6a2c1 349 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 350 }
AzureIoTClient 6:641a9672db08 351 else
AzureIoTClient 6:641a9672db08 352 {
AzureIoTClient 21:f9c433d8e6ca 353 /* Codes_SRS_CBS_01_077: [ On success, `cbs_open_async` shall return 0. ]*/
AzureIoTClient 6:641a9672db08 354 result = 0;
AzureIoTClient 6:641a9672db08 355 }
AzureIoTClient 6:641a9672db08 356 }
Azure.IoT Build 0:6ae2f7bca550 357
AzureIoTClient 6:641a9672db08 358 return result;
Azure.IoT Build 0:6ae2f7bca550 359 }
Azure.IoT Build 0:6ae2f7bca550 360
Azure.IoT Build 0:6ae2f7bca550 361 int cbs_close(CBS_HANDLE cbs)
Azure.IoT Build 0:6ae2f7bca550 362 {
AzureIoTClient 6:641a9672db08 363 int result;
Azure.IoT Build 0:6ae2f7bca550 364
AzureIoTClient 6:641a9672db08 365 if (cbs == NULL)
AzureIoTClient 6:641a9672db08 366 {
AzureIoTClient 21:f9c433d8e6ca 367 /* Codes_SRS_CBS_01_045: [ If the argument `cbs` is NULL, `cbs_close` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 368 LogError("NULL cbs handle");
AzureIoTClient 21:f9c433d8e6ca 369 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 370 }
AzureIoTClient 21:f9c433d8e6ca 371 else if (cbs->cbs_state == CBS_STATE_CLOSED)
AzureIoTClient 21:f9c433d8e6ca 372 {
AzureIoTClient 21:f9c433d8e6ca 373 /* Codes_SRS_CBS_01_047: [ `cbs_close` when closed shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 374 /* Codes_SRS_CBS_01_048: [ `cbs_close` when not opened shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 375 LogError("Already closed");
AzureIoTClient 19:000ab4e6a2c1 376 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 377 }
AzureIoTClient 6:641a9672db08 378 else
AzureIoTClient 6:641a9672db08 379 {
AzureIoTClient 21:f9c433d8e6ca 380 /* Codes_SRS_CBS_01_044: [ `cbs_close` shall close the CBS instance by calling `amqpmanagement_close` on the underlying AMQP management handle. ]*/
AzureIoTClient 6:641a9672db08 381 if (amqpmanagement_close(cbs->amqp_management) != 0)
AzureIoTClient 6:641a9672db08 382 {
AzureIoTClient 21:f9c433d8e6ca 383 /* Codes_SRS_CBS_01_046: [ If `amqpmanagement_close` fails, `cbs_close` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 384 LogError("Failed closing AMQP management instance");
AzureIoTClient 19:000ab4e6a2c1 385 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 386 }
AzureIoTClient 6:641a9672db08 387 else
AzureIoTClient 6:641a9672db08 388 {
AzureIoTClient 21:f9c433d8e6ca 389 if (cbs->cbs_state == CBS_STATE_OPENING)
AzureIoTClient 21:f9c433d8e6ca 390 {
AzureIoTClient 21:f9c433d8e6ca 391 /* Codes_SRS_CBS_01_079: [ If `cbs_close` is called while OPENING, the `on_cbs_open_complete` callback shall be called with `CBS_OPEN_CANCELLED`, while passing the `on_cbs_open_complete_context` as argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 392 cbs->on_cbs_open_complete(cbs->on_cbs_open_complete_context, CBS_OPEN_CANCELLED);
AzureIoTClient 21:f9c433d8e6ca 393 }
AzureIoTClient 21:f9c433d8e6ca 394
AzureIoTClient 21:f9c433d8e6ca 395 cbs->cbs_state = CBS_STATE_CLOSED;
AzureIoTClient 21:f9c433d8e6ca 396
AzureIoTClient 21:f9c433d8e6ca 397 /* Codes_SRS_CBS_01_080: [ On success, `cbs_close` shall return 0. ]*/
AzureIoTClient 6:641a9672db08 398 result = 0;
AzureIoTClient 6:641a9672db08 399 }
AzureIoTClient 6:641a9672db08 400 }
Azure.IoT Build 0:6ae2f7bca550 401
AzureIoTClient 6:641a9672db08 402 return result;
Azure.IoT Build 0:6ae2f7bca550 403 }
Azure.IoT Build 0:6ae2f7bca550 404
AzureIoTClient 21:f9c433d8e6ca 405 int cbs_put_token_async(CBS_HANDLE cbs, const char* type, const char* audience, const char* token, ON_CBS_OPERATION_COMPLETE on_cbs_put_token_complete, void* on_cbs_put_token_complete_context)
Azure.IoT Build 0:6ae2f7bca550 406 {
AzureIoTClient 6:641a9672db08 407 int result;
Azure.IoT Build 0:6ae2f7bca550 408
AzureIoTClient 21:f9c433d8e6ca 409 /* Codes_SRS_CBS_01_083: [ `on_cbs_put_token_complete_context` shall be allowed to be NULL. ]*/
AzureIoTClient 6:641a9672db08 410 if ((cbs == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 411 (type == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 412 (audience == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 413 (token == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 414 (on_cbs_put_token_complete == NULL))
AzureIoTClient 6:641a9672db08 415 {
AzureIoTClient 21:f9c433d8e6ca 416 /* Codes_SRS_CBS_01_050: [ If any of the arguments `cbs`, `type`, `audience`, `token` or `on_cbs_put_token_complete` is NULL `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 417 LogError("Bad arguments: cbs = %p, type = %p, audience = %p, token = %p, on_cbs_put_token_complete = %p",
AzureIoTClient 21:f9c433d8e6ca 418 cbs, type, audience, token, on_cbs_put_token_complete);
AzureIoTClient 21:f9c433d8e6ca 419 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 420 }
AzureIoTClient 21:f9c433d8e6ca 421 else if ((cbs->cbs_state == CBS_STATE_CLOSED) ||
AzureIoTClient 21:f9c433d8e6ca 422 (cbs->cbs_state == CBS_STATE_ERROR))
AzureIoTClient 21:f9c433d8e6ca 423 {
AzureIoTClient 21:f9c433d8e6ca 424 /* Codes_SRS_CBS_01_058: [ If `cbs_put_token_async` is called when the CBS instance is not yet open or in error, it shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 425 LogError("put token called while closed or in error");
AzureIoTClient 19:000ab4e6a2c1 426 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 427 }
AzureIoTClient 6:641a9672db08 428 else
AzureIoTClient 6:641a9672db08 429 {
AzureIoTClient 21:f9c433d8e6ca 430 /* Codes_SRS_CBS_01_049: [ `cbs_put_token_async` shall construct a request message for the `put-token` operation. ]*/
AzureIoTClient 6:641a9672db08 431 MESSAGE_HANDLE message = message_create();
AzureIoTClient 6:641a9672db08 432 if (message == NULL)
AzureIoTClient 6:641a9672db08 433 {
AzureIoTClient 21:f9c433d8e6ca 434 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 435 LogError("message_create failed");
AzureIoTClient 19:000ab4e6a2c1 436 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 437 }
AzureIoTClient 6:641a9672db08 438 else
AzureIoTClient 6:641a9672db08 439 {
AzureIoTClient 6:641a9672db08 440 AMQP_VALUE token_value = amqpvalue_create_string(token);
AzureIoTClient 6:641a9672db08 441 if (token_value == NULL)
AzureIoTClient 6:641a9672db08 442 {
AzureIoTClient 21:f9c433d8e6ca 443 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 444 LogError("Failed creating token AMQP value");
AzureIoTClient 19:000ab4e6a2c1 445 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 446 }
AzureIoTClient 6:641a9672db08 447 else
AzureIoTClient 6:641a9672db08 448 {
AzureIoTClient 21:f9c433d8e6ca 449 /* Codes_SRS_CBS_01_009: [ The body of the message MUST contain the token. ]*/
AzureIoTClient 6:641a9672db08 450 if (message_set_body_amqp_value(message, token_value) != 0)
AzureIoTClient 6:641a9672db08 451 {
AzureIoTClient 21:f9c433d8e6ca 452 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 453 LogError("Failed setting the token in the message body");
AzureIoTClient 19:000ab4e6a2c1 454 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 455 }
AzureIoTClient 6:641a9672db08 456 else
AzureIoTClient 6:641a9672db08 457 {
AzureIoTClient 6:641a9672db08 458 AMQP_VALUE application_properties = amqpvalue_create_map();
AzureIoTClient 6:641a9672db08 459 if (application_properties == NULL)
AzureIoTClient 6:641a9672db08 460 {
AzureIoTClient 21:f9c433d8e6ca 461 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 462 LogError("Failed creating application properties map");
AzureIoTClient 19:000ab4e6a2c1 463 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 464 }
AzureIoTClient 6:641a9672db08 465 else
AzureIoTClient 6:641a9672db08 466 {
AzureIoTClient 6:641a9672db08 467 if (add_string_key_value_pair_to_map(application_properties, "name", audience) != 0)
AzureIoTClient 6:641a9672db08 468 {
AzureIoTClient 19:000ab4e6a2c1 469 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 470 }
AzureIoTClient 6:641a9672db08 471 else
AzureIoTClient 6:641a9672db08 472 {
AzureIoTClient 6:641a9672db08 473 if (message_set_application_properties(message, application_properties) != 0)
AzureIoTClient 6:641a9672db08 474 {
AzureIoTClient 21:f9c433d8e6ca 475 /* Codes_SRS_CBS_01_072: [ If constructing the message fails, `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 476 LogError("Failed setting message application properties");
AzureIoTClient 19:000ab4e6a2c1 477 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 478 }
AzureIoTClient 6:641a9672db08 479 else
AzureIoTClient 6:641a9672db08 480 {
AzureIoTClient 21:f9c433d8e6ca 481 CBS_OPERATION* cbs_operation = (CBS_OPERATION*)malloc(sizeof(CBS_OPERATION));
AzureIoTClient 21:f9c433d8e6ca 482 if (cbs_operation == NULL)
AzureIoTClient 6:641a9672db08 483 {
AzureIoTClient 21:f9c433d8e6ca 484 LogError("Failed allocating CBS operation instance");
AzureIoTClient 19:000ab4e6a2c1 485 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 486 }
AzureIoTClient 6:641a9672db08 487 else
AzureIoTClient 6:641a9672db08 488 {
AzureIoTClient 21:f9c433d8e6ca 489 LIST_ITEM_HANDLE list_item;
AzureIoTClient 21:f9c433d8e6ca 490
AzureIoTClient 21:f9c433d8e6ca 491 cbs_operation->on_cbs_operation_complete = on_cbs_put_token_complete;
AzureIoTClient 21:f9c433d8e6ca 492 cbs_operation->on_cbs_operation_complete_context = on_cbs_put_token_complete_context;
AzureIoTClient 21:f9c433d8e6ca 493 cbs_operation->pending_operations = cbs->pending_operations;
AzureIoTClient 21:f9c433d8e6ca 494
AzureIoTClient 21:f9c433d8e6ca 495 list_item = singlylinkedlist_add(cbs->pending_operations, cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 496 if (list_item == NULL)
AzureIoTClient 6:641a9672db08 497 {
AzureIoTClient 21:f9c433d8e6ca 498 free(cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 499 LogError("Failed adding pending operation to list");
AzureIoTClient 19:000ab4e6a2c1 500 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 501 }
AzureIoTClient 6:641a9672db08 502 else
AzureIoTClient 6:641a9672db08 503 {
AzureIoTClient 21:f9c433d8e6ca 504 /* Codes_SRS_CBS_01_051: [ `cbs_put_token_async` shall start the AMQP management operation by calling `amqpmanagement_start_operation`, while passing to it: ]*/
AzureIoTClient 21:f9c433d8e6ca 505 /* Codes_SRS_CBS_01_052: [ The `amqp_management` argument shall be the one for the AMQP management instance created in `cbs_create`. ]*/
AzureIoTClient 21:f9c433d8e6ca 506 /* Codes_SRS_CBS_01_053: [ The `operation` argument shall be `put-token`. ]*/
AzureIoTClient 21:f9c433d8e6ca 507 /* Codes_SRS_CBS_01_054: [ The `type` argument shall be set to the `type` argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 508 /* Codes_SRS_CBS_01_055: [ The `locales` argument shall be set to NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 509 /* Codes_SRS_CBS_01_056: [ The `message` argument shall be the message constructed earlier according to the CBS spec. ]*/
AzureIoTClient 21:f9c433d8e6ca 510 /* Codes_SRS_CBS_01_057: [ The arguments `on_operation_complete` and `context` shall be set to a callback that is to be called by the AMQP management module when the operation is complete. ]*/
AzureIoTClient 21:f9c433d8e6ca 511 /* Codes_SRS_CBS_01_005: [ operation No string "put-token" ]*/
AzureIoTClient 21:f9c433d8e6ca 512 /* Codes_SRS_CBS_01_006: [ Type No string The type of the token being put, e.g., "amqp:jwt". ]*/
AzureIoTClient 21:f9c433d8e6ca 513 /* Codes_SRS_CBS_01_007: [ name No string The "audience" to which the token applies. ]*/
AzureIoTClient 21:f9c433d8e6ca 514 if (amqpmanagement_start_operation(cbs->amqp_management, "put-token", type, NULL, message, on_amqp_management_operation_complete, list_item) != 0)
AzureIoTClient 21:f9c433d8e6ca 515 {
AzureIoTClient 21:f9c433d8e6ca 516 singlylinkedlist_remove(cbs->pending_operations, list_item);
AzureIoTClient 21:f9c433d8e6ca 517 free(cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 518 /* Codes_SRS_CBS_01_084: [ If `amqpmanagement_start_operation` fails `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 519 LogError("Failed starting AMQP management operation");
AzureIoTClient 21:f9c433d8e6ca 520 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 521 }
AzureIoTClient 21:f9c433d8e6ca 522 else
AzureIoTClient 21:f9c433d8e6ca 523 {
AzureIoTClient 21:f9c433d8e6ca 524 /* Codes_SRS_CBS_01_081: [ On success `cbs_put_token_async` shall return 0. ]*/
AzureIoTClient 21:f9c433d8e6ca 525 result = 0;
AzureIoTClient 21:f9c433d8e6ca 526 }
AzureIoTClient 6:641a9672db08 527 }
AzureIoTClient 6:641a9672db08 528 }
AzureIoTClient 6:641a9672db08 529 }
AzureIoTClient 6:641a9672db08 530 }
Azure.IoT Build 0:6ae2f7bca550 531
AzureIoTClient 6:641a9672db08 532 amqpvalue_destroy(application_properties);
AzureIoTClient 6:641a9672db08 533 }
Azure.IoT Build 0:6ae2f7bca550 534
AzureIoTClient 6:641a9672db08 535 amqpvalue_destroy(token_value);
AzureIoTClient 6:641a9672db08 536 }
AzureIoTClient 6:641a9672db08 537 }
Azure.IoT Build 0:6ae2f7bca550 538
AzureIoTClient 6:641a9672db08 539 message_destroy(message);
AzureIoTClient 6:641a9672db08 540 }
AzureIoTClient 6:641a9672db08 541 }
Azure.IoT Build 0:6ae2f7bca550 542
AzureIoTClient 6:641a9672db08 543 return result;
Azure.IoT Build 0:6ae2f7bca550 544 }
Azure.IoT Build 0:6ae2f7bca550 545
AzureIoTClient 21:f9c433d8e6ca 546 int cbs_delete_token_async(CBS_HANDLE cbs, const char* type, const char* audience, ON_CBS_OPERATION_COMPLETE on_cbs_delete_token_complete, void* on_cbs_delete_token_complete_context)
Azure.IoT Build 0:6ae2f7bca550 547 {
AzureIoTClient 6:641a9672db08 548 int result;
Azure.IoT Build 0:6ae2f7bca550 549
AzureIoTClient 21:f9c433d8e6ca 550 /* Codes_SRS_CBS_01_086: [ `on_cbs_delete_token_complete_context` shall be allowed to be NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 551 if ((cbs == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 552 (type == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 553 (audience == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 554 (on_cbs_delete_token_complete == NULL))
AzureIoTClient 6:641a9672db08 555 {
AzureIoTClient 21:f9c433d8e6ca 556 /* Codes_SRS_CBS_01_060: [ If any of the arguments `cbs`, `type`, `audience` or `on_cbs_delete_token_complete` is NULL `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 557 LogError("Bad arguments: cbs = %p, type = %p, audience = %p, on_cbs_delete_token_complete = %p",
AzureIoTClient 21:f9c433d8e6ca 558 cbs, type, audience, on_cbs_delete_token_complete);
AzureIoTClient 21:f9c433d8e6ca 559 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 560 }
AzureIoTClient 21:f9c433d8e6ca 561 else if ((cbs->cbs_state == CBS_STATE_CLOSED) ||
AzureIoTClient 21:f9c433d8e6ca 562 (cbs->cbs_state == CBS_STATE_ERROR))
AzureIoTClient 21:f9c433d8e6ca 563 {
AzureIoTClient 21:f9c433d8e6ca 564 /* Codes_SRS_CBS_01_067: [ If `cbs_delete_token_async` is called when the CBS instance is not yet open or in error, it shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 565 LogError("put token called while closed or in error");
AzureIoTClient 19:000ab4e6a2c1 566 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 567 }
AzureIoTClient 6:641a9672db08 568 else
AzureIoTClient 6:641a9672db08 569 {
AzureIoTClient 21:f9c433d8e6ca 570 /* Codes_SRS_CBS_01_025: [ The body of the message MUST be empty. ]*/
AzureIoTClient 21:f9c433d8e6ca 571 /* Codes_SRS_CBS_01_059: [ `cbs_delete_token_async` shall construct a request message for the `delete-token` operation. ]*/
AzureIoTClient 6:641a9672db08 572 MESSAGE_HANDLE message = message_create();
AzureIoTClient 6:641a9672db08 573 if (message == NULL)
AzureIoTClient 6:641a9672db08 574 {
AzureIoTClient 21:f9c433d8e6ca 575 /* Codes_SRS_CBS_01_071: [ If constructing the message fails, `cbs_delete_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 576 LogError("message_create failed");
AzureIoTClient 19:000ab4e6a2c1 577 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 578 }
AzureIoTClient 6:641a9672db08 579 else
AzureIoTClient 6:641a9672db08 580 {
AzureIoTClient 6:641a9672db08 581 AMQP_VALUE application_properties = amqpvalue_create_map();
AzureIoTClient 6:641a9672db08 582 if (application_properties == NULL)
AzureIoTClient 6:641a9672db08 583 {
AzureIoTClient 21:f9c433d8e6ca 584 /* Codes_SRS_CBS_01_071: [ If constructing the message fails, `cbs_delete_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 585 LogError("Failed creating application properties map");
AzureIoTClient 19:000ab4e6a2c1 586 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 587 }
AzureIoTClient 6:641a9672db08 588 else
AzureIoTClient 6:641a9672db08 589 {
AzureIoTClient 6:641a9672db08 590 if (add_string_key_value_pair_to_map(application_properties, "name", audience) != 0)
AzureIoTClient 6:641a9672db08 591 {
AzureIoTClient 19:000ab4e6a2c1 592 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 593 }
AzureIoTClient 6:641a9672db08 594 else
AzureIoTClient 6:641a9672db08 595 {
AzureIoTClient 21:f9c433d8e6ca 596 /* Codes_SRS_CBS_01_021: [ The request message has the following application-properties: ]*/
AzureIoTClient 6:641a9672db08 597 if (message_set_application_properties(message, application_properties) != 0)
AzureIoTClient 6:641a9672db08 598 {
AzureIoTClient 21:f9c433d8e6ca 599 /* Codes_SRS_CBS_01_071: [ If constructing the message fails, `cbs_delete_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 600 LogError("Failed setting message application properties");
AzureIoTClient 19:000ab4e6a2c1 601 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 602 }
AzureIoTClient 6:641a9672db08 603 else
AzureIoTClient 6:641a9672db08 604 {
AzureIoTClient 21:f9c433d8e6ca 605 CBS_OPERATION* cbs_operation = (CBS_OPERATION*)malloc(sizeof(CBS_OPERATION));
AzureIoTClient 21:f9c433d8e6ca 606 if (cbs_operation == NULL)
AzureIoTClient 6:641a9672db08 607 {
AzureIoTClient 21:f9c433d8e6ca 608 LogError("Failed allocating CBS operation instance");
AzureIoTClient 19:000ab4e6a2c1 609 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 610 }
AzureIoTClient 6:641a9672db08 611 else
AzureIoTClient 6:641a9672db08 612 {
AzureIoTClient 21:f9c433d8e6ca 613 LIST_ITEM_HANDLE list_item;
AzureIoTClient 21:f9c433d8e6ca 614
AzureIoTClient 21:f9c433d8e6ca 615 cbs_operation->on_cbs_operation_complete = on_cbs_delete_token_complete;
AzureIoTClient 21:f9c433d8e6ca 616 cbs_operation->on_cbs_operation_complete_context = on_cbs_delete_token_complete_context;
AzureIoTClient 21:f9c433d8e6ca 617 cbs_operation->pending_operations = cbs->pending_operations;
AzureIoTClient 21:f9c433d8e6ca 618
AzureIoTClient 21:f9c433d8e6ca 619 list_item = singlylinkedlist_add(cbs->pending_operations, cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 620 if (list_item == NULL)
AzureIoTClient 6:641a9672db08 621 {
AzureIoTClient 21:f9c433d8e6ca 622 free(cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 623 LogError("Failed adding pending operation to list");
AzureIoTClient 19:000ab4e6a2c1 624 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 625 }
AzureIoTClient 6:641a9672db08 626 else
AzureIoTClient 6:641a9672db08 627 {
AzureIoTClient 21:f9c433d8e6ca 628 /* Codes_SRS_CBS_01_061: [ `cbs_delete_token_async` shall start the AMQP management operation by calling `amqpmanagement_start_operation`, while passing to it: ]*/
AzureIoTClient 21:f9c433d8e6ca 629 /* Codes_SRS_CBS_01_085: [ The `amqp_management` argument shall be the one for the AMQP management instance created in `cbs_create`. ]*/
AzureIoTClient 21:f9c433d8e6ca 630 /* Codes_SRS_CBS_01_062: [ The `operation` argument shall be `delete-token`. ]*/
AzureIoTClient 21:f9c433d8e6ca 631 /* Codes_SRS_CBS_01_063: [ The `type` argument shall be set to the `type` argument. ]*/
AzureIoTClient 21:f9c433d8e6ca 632 /* Codes_SRS_CBS_01_064: [ The `locales` argument shall be set to NULL. ]*/
AzureIoTClient 21:f9c433d8e6ca 633 /* Codes_SRS_CBS_01_065: [ The `message` argument shall be the message constructed earlier according to the CBS spec. ]*/
AzureIoTClient 21:f9c433d8e6ca 634 /* Codes_SRS_CBS_01_066: [ The arguments `on_operation_complete` and `context` shall be set to a callback that is to be called by the AMQP management module when the operation is complete. ]*/
AzureIoTClient 21:f9c433d8e6ca 635 /* Codes_SRS_CBS_01_020: [ To instruct a peer to delete a token associated with a specific audience, a "delete-token" message can be sent to the CBS Node ]*/
AzureIoTClient 21:f9c433d8e6ca 636 /* Codes_SRS_CBS_01_022: [ operation Yes string "delete-token" ]*/
AzureIoTClient 21:f9c433d8e6ca 637 /* Codes_SRS_CBS_01_023: [ Type Yes string The type of the token being deleted, e.g., "amqp:jwt". ]*/
AzureIoTClient 21:f9c433d8e6ca 638 /* Codes_SRS_CBS_01_024: [ name Yes string The "audience" of the token being deleted. ]*/
AzureIoTClient 21:f9c433d8e6ca 639 if (amqpmanagement_start_operation(cbs->amqp_management, "delete-token", type, NULL, message, on_amqp_management_operation_complete, list_item) != 0)
AzureIoTClient 21:f9c433d8e6ca 640 {
AzureIoTClient 21:f9c433d8e6ca 641 /* Codes_SRS_CBS_01_087: [ If `amqpmanagement_start_operation` fails `cbs_put_token_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 642 singlylinkedlist_remove(cbs->pending_operations, list_item);
AzureIoTClient 21:f9c433d8e6ca 643 free(cbs_operation);
AzureIoTClient 21:f9c433d8e6ca 644 LogError("Failed starting AMQP management operation");
AzureIoTClient 21:f9c433d8e6ca 645 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 646 }
AzureIoTClient 21:f9c433d8e6ca 647 else
AzureIoTClient 21:f9c433d8e6ca 648 {
AzureIoTClient 21:f9c433d8e6ca 649 /* Codes_SRS_CBS_01_082: [ On success `cbs_delete_token_async` shall return 0. ]*/
AzureIoTClient 21:f9c433d8e6ca 650 result = 0;
AzureIoTClient 21:f9c433d8e6ca 651 }
AzureIoTClient 6:641a9672db08 652 }
AzureIoTClient 6:641a9672db08 653 }
AzureIoTClient 6:641a9672db08 654 }
AzureIoTClient 6:641a9672db08 655 }
Azure.IoT Build 0:6ae2f7bca550 656
AzureIoTClient 6:641a9672db08 657 amqpvalue_destroy(application_properties);
AzureIoTClient 6:641a9672db08 658 }
Azure.IoT Build 0:6ae2f7bca550 659
AzureIoTClient 6:641a9672db08 660 message_destroy(message);
AzureIoTClient 6:641a9672db08 661 }
AzureIoTClient 6:641a9672db08 662 }
AzureIoTClient 6:641a9672db08 663 return result;
AzureIoTClient 6:641a9672db08 664 }
Azure.IoT Build 0:6ae2f7bca550 665
AzureIoTClient 21:f9c433d8e6ca 666 int cbs_set_trace(CBS_HANDLE cbs, bool trace_on)
AzureIoTClient 6:641a9672db08 667 {
AzureIoTClient 21:f9c433d8e6ca 668 int result;
AzureIoTClient 21:f9c433d8e6ca 669
AzureIoTClient 21:f9c433d8e6ca 670 if (cbs == NULL)
AzureIoTClient 6:641a9672db08 671 {
AzureIoTClient 21:f9c433d8e6ca 672 /* Codes_SRS_CBS_01_090: [ If the argument `cbs` is NULL, `cbs_set_trace` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 673 LogError("NULL cbs handle");
AzureIoTClient 21:f9c433d8e6ca 674 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 675 }
AzureIoTClient 21:f9c433d8e6ca 676 else
AzureIoTClient 21:f9c433d8e6ca 677 {
AzureIoTClient 21:f9c433d8e6ca 678 /* Codes_SRS_CBS_01_088: [ `cbs_set_trace` shall enable or disable tracing by calling `amqpmanagement_set_trace` to pass down the `trace_on` value. ]*/
AzureIoTClient 21:f9c433d8e6ca 679 amqpmanagement_set_trace(cbs->amqp_management, trace_on);
AzureIoTClient 21:f9c433d8e6ca 680
AzureIoTClient 21:f9c433d8e6ca 681 /* Codes_SRS_CBS_01_089: [ On success, `cbs_set_trace` shall return 0. ]*/
AzureIoTClient 21:f9c433d8e6ca 682 result = 0;
AzureIoTClient 21:f9c433d8e6ca 683 }
AzureIoTClient 21:f9c433d8e6ca 684
AzureIoTClient 21:f9c433d8e6ca 685 return result;
Azure.IoT Build 0:6ae2f7bca550 686 }