A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jun 30 10:41:22 2017 -0700
Revision:
28:add19eb7defa
Parent:
27:d74f1cea23e1
Child:
39:e7c983378f41
1.1.18

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