Part of TI's mqtt

Dependents:   mqtt_V1 cc3100_Test_mqtt_CM3

Committer:
dflet
Date:
Sat Jun 06 13:29:08 2015 +0000
Revision:
0:547251f42a60
Part of mqtt_V1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dflet 0:547251f42a60 1 /******************************************************************************
dflet 0:547251f42a60 2 *
dflet 0:547251f42a60 3 * Copyright (C) 2014 Texas Instruments Incorporated
dflet 0:547251f42a60 4 *
dflet 0:547251f42a60 5 * All rights reserved. Property of Texas Instruments Incorporated.
dflet 0:547251f42a60 6 * Restricted rights to use, duplicate or disclose this code are
dflet 0:547251f42a60 7 * granted through contract.
dflet 0:547251f42a60 8 *
dflet 0:547251f42a60 9 * The program may not be used without the written permission of
dflet 0:547251f42a60 10 * Texas Instruments Incorporated or against the terms and conditions
dflet 0:547251f42a60 11 * stipulated in the agreement under which this program has been supplied,
dflet 0:547251f42a60 12 * and under no circumstances can it be used with non-TI connectivity device.
dflet 0:547251f42a60 13 *
dflet 0:547251f42a60 14 ******************************************************************************/
dflet 0:547251f42a60 15
dflet 0:547251f42a60 16 #include "server_util.h"
dflet 0:547251f42a60 17 #include "client_mgmt.h"
dflet 0:547251f42a60 18 #include "server_pkts.h"
dflet 0:547251f42a60 19
dflet 0:547251f42a60 20 namespace mbed_mqtt {
dflet 0:547251f42a60 21
dflet 0:547251f42a60 22 #ifndef CFG_SR_MAX_CL_ID_SIZE
dflet 0:547251f42a60 23 #define MAX_CLIENT_ID_LEN 64
dflet 0:547251f42a60 24 #else
dflet 0:547251f42a60 25 #define MAX_CLIENT_ID_LEN CFG_SR_MAX_CL_ID_SIZE
dflet 0:547251f42a60 26 #endif
dflet 0:547251f42a60 27
dflet 0:547251f42a60 28 #ifndef CFG_SR_MAX_NUM_CLIENT
dflet 0:547251f42a60 29 #define MAX_CLIENTS 16 /* Must not exceed 32 */
dflet 0:547251f42a60 30 #else
dflet 0:547251f42a60 31 #define MAX_CLIENTS CFG_SR_MAX_NUM_CLIENT
dflet 0:547251f42a60 32
dflet 0:547251f42a60 33 #if (CFG_SR_MAX_NUM_CLIENT > 32)
dflet 0:547251f42a60 34 #error "CFG_SR_MAX_NUM_CLIENT must not exceed 32"
dflet 0:547251f42a60 35 #endif
dflet 0:547251f42a60 36 #endif
dflet 0:547251f42a60 37
dflet 0:547251f42a60 38 static struct client_usr {
dflet 0:547251f42a60 39
dflet 0:547251f42a60 40 void *ctx; /* Client net */
dflet 0:547251f42a60 41 void *app; /* Client app */
dflet 0:547251f42a60 42
dflet 0:547251f42a60 43 void *will; /* Will topic */
dflet 0:547251f42a60 44 uint32_t index;
dflet 0:547251f42a60 45 uint32_t n_sub;
dflet 0:547251f42a60 46
dflet 0:547251f42a60 47 #define MQ_CONNECT_FLAG 0x00000001
dflet 0:547251f42a60 48 #define CLEAN_SESS_FLAG 0x00000002
dflet 0:547251f42a60 49 #define ASSIGNMENT_FLAG 0x00000004 /* No state or connected */
dflet 0:547251f42a60 50
dflet 0:547251f42a60 51 uint32_t flags;
dflet 0:547251f42a60 52
dflet 0:547251f42a60 53 char client_id[MAX_CLIENT_ID_LEN];
dflet 0:547251f42a60 54
dflet 0:547251f42a60 55 struct pub_qos2_cq qos2_rx_cq;
dflet 0:547251f42a60 56 struct pub_qos2_cq qos2_tx_cq;
dflet 0:547251f42a60 57
dflet 0:547251f42a60 58 } users[MAX_CLIENTS];
dflet 0:547251f42a60 59
dflet 0:547251f42a60 60 // TBD consistency between inline and macro functions
dflet 0:547251f42a60 61
dflet 0:547251f42a60 62 static inline bool is_connected(struct client_usr *cl_usr)
dflet 0:547251f42a60 63 {
dflet 0:547251f42a60 64 return (cl_usr->flags & MQ_CONNECT_FLAG)? true : false;
dflet 0:547251f42a60 65 }
dflet 0:547251f42a60 66
dflet 0:547251f42a60 67 static inline bool has_clean_session(struct client_usr *cl_usr)
dflet 0:547251f42a60 68 {
dflet 0:547251f42a60 69 return (cl_usr->flags & CLEAN_SESS_FLAG)? true : false;
dflet 0:547251f42a60 70 }
dflet 0:547251f42a60 71
dflet 0:547251f42a60 72 static inline bool is_assigned(struct client_usr *cl_usr)
dflet 0:547251f42a60 73 {
dflet 0:547251f42a60 74 return (cl_usr->flags & ASSIGNMENT_FLAG)? true : false;
dflet 0:547251f42a60 75 }
dflet 0:547251f42a60 76
dflet 0:547251f42a60 77 static inline void set_connect_state(struct client_usr *cl_usr,
dflet 0:547251f42a60 78 bool connected)
dflet 0:547251f42a60 79 {
dflet 0:547251f42a60 80 if(connected)
dflet 0:547251f42a60 81 cl_usr->flags |= MQ_CONNECT_FLAG;
dflet 0:547251f42a60 82 else
dflet 0:547251f42a60 83 cl_usr->flags &= ~MQ_CONNECT_FLAG;
dflet 0:547251f42a60 84 }
dflet 0:547251f42a60 85
dflet 0:547251f42a60 86 static inline void set_clean_session(struct client_usr *cl_usr,
dflet 0:547251f42a60 87 bool clean_session)
dflet 0:547251f42a60 88 {
dflet 0:547251f42a60 89 if(clean_session)
dflet 0:547251f42a60 90 cl_usr->flags |= CLEAN_SESS_FLAG;
dflet 0:547251f42a60 91 else
dflet 0:547251f42a60 92 cl_usr->flags &= ~CLEAN_SESS_FLAG;
dflet 0:547251f42a60 93 }
dflet 0:547251f42a60 94
dflet 0:547251f42a60 95 static inline void set_assigned(struct client_usr *cl_usr,
dflet 0:547251f42a60 96 bool assignment)
dflet 0:547251f42a60 97 {
dflet 0:547251f42a60 98 if(assignment)
dflet 0:547251f42a60 99 cl_usr->flags |= ASSIGNMENT_FLAG;
dflet 0:547251f42a60 100 else
dflet 0:547251f42a60 101 cl_usr->flags &= ~ASSIGNMENT_FLAG;
dflet 0:547251f42a60 102 }
dflet 0:547251f42a60 103
dflet 0:547251f42a60 104 static void cl_usr_reset(struct client_usr *cl_usr)
dflet 0:547251f42a60 105 {
dflet 0:547251f42a60 106 cl_usr->ctx = NULL;
dflet 0:547251f42a60 107 cl_usr->app = NULL;
dflet 0:547251f42a60 108 cl_usr->will = NULL;
dflet 0:547251f42a60 109
dflet 0:547251f42a60 110 cl_usr->n_sub = 0;
dflet 0:547251f42a60 111 cl_usr->flags = 0;
dflet 0:547251f42a60 112
dflet 0:547251f42a60 113 cl_usr->client_id[0] = '\0';
dflet 0:547251f42a60 114
dflet 0:547251f42a60 115 qos2_pub_cq_reset(&cl_usr->qos2_rx_cq);
dflet 0:547251f42a60 116 qos2_pub_cq_reset(&cl_usr->qos2_tx_cq);
dflet 0:547251f42a60 117 }
dflet 0:547251f42a60 118
dflet 0:547251f42a60 119 static void cl_usr_init(void)
dflet 0:547251f42a60 120 {
dflet 0:547251f42a60 121 int32_t idx = 0;
dflet 0:547251f42a60 122 for(idx = 0; idx < MAX_CLIENTS; idx++) {
dflet 0:547251f42a60 123 struct client_usr *cl_usr = users + idx;
dflet 0:547251f42a60 124 cl_usr->index = idx;
dflet 0:547251f42a60 125
dflet 0:547251f42a60 126 cl_usr_reset(cl_usr);
dflet 0:547251f42a60 127 }
dflet 0:547251f42a60 128 }
dflet 0:547251f42a60 129
dflet 0:547251f42a60 130 static void cl_usr_free(struct client_usr *cl_usr)
dflet 0:547251f42a60 131 {
dflet 0:547251f42a60 132 cl_usr_reset(cl_usr);
dflet 0:547251f42a60 133 cl_usr->flags &= ~(MQ_CONNECT_FLAG |
dflet 0:547251f42a60 134 CLEAN_SESS_FLAG |
dflet 0:547251f42a60 135 ASSIGNMENT_FLAG);
dflet 0:547251f42a60 136 }
dflet 0:547251f42a60 137
dflet 0:547251f42a60 138 void cl_sub_count_add(void *usr_cl)
dflet 0:547251f42a60 139 {
dflet 0:547251f42a60 140 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 141
dflet 0:547251f42a60 142 if(is_connected(cl_usr)) {
dflet 0:547251f42a60 143 cl_usr->n_sub++;
dflet 0:547251f42a60 144 USR_INFO("%s has added a new sub, now total is %u\n\r",
dflet 0:547251f42a60 145 cl_usr->client_id, cl_usr->n_sub);
dflet 0:547251f42a60 146
dflet 0:547251f42a60 147 }
dflet 0:547251f42a60 148
dflet 0:547251f42a60 149 return;
dflet 0:547251f42a60 150 }
dflet 0:547251f42a60 151
dflet 0:547251f42a60 152 void cl_sub_count_del(void *usr_cl)
dflet 0:547251f42a60 153 {
dflet 0:547251f42a60 154 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 155
dflet 0:547251f42a60 156 if(is_connected(cl_usr)) {
dflet 0:547251f42a60 157 cl_usr->n_sub--;
dflet 0:547251f42a60 158 USR_INFO("%s has deleted a sub, now total is %u\n\r",
dflet 0:547251f42a60 159 cl_usr->client_id, cl_usr->n_sub);
dflet 0:547251f42a60 160 }
dflet 0:547251f42a60 161
dflet 0:547251f42a60 162 return;
dflet 0:547251f42a60 163 }
dflet 0:547251f42a60 164
dflet 0:547251f42a60 165 /*----------------------------------------------------------------------------
dflet 0:547251f42a60 166 * QoS2 PUB RX Message handling mechanism and associated house-keeping
dflet 0:547251f42a60 167 *--------------------------------------------------------------------------*/
dflet 0:547251f42a60 168 static inline bool qos2_pub_rx_logup(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 169 {
dflet 0:547251f42a60 170 return qos2_pub_cq_logup(&cl_usr->qos2_rx_cq, msg_id);
dflet 0:547251f42a60 171 }
dflet 0:547251f42a60 172
dflet 0:547251f42a60 173 static inline bool ack2_msg_id_logup(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 174 {
dflet 0:547251f42a60 175 return qos2_pub_cq_logup(&cl_usr->qos2_tx_cq, msg_id);
dflet 0:547251f42a60 176 }
dflet 0:547251f42a60 177
dflet 0:547251f42a60 178 static inline bool qos2_pub_rx_unlog(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 179 {
dflet 0:547251f42a60 180 return qos2_pub_cq_unlog(&cl_usr->qos2_rx_cq, msg_id);
dflet 0:547251f42a60 181 }
dflet 0:547251f42a60 182
dflet 0:547251f42a60 183 static inline bool ack2_msg_id_unlog(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 184 {
dflet 0:547251f42a60 185 return qos2_pub_cq_unlog(&cl_usr->qos2_tx_cq, msg_id);
dflet 0:547251f42a60 186 }
dflet 0:547251f42a60 187
dflet 0:547251f42a60 188 static inline bool qos2_pub_rx_is_done(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 189 {
dflet 0:547251f42a60 190 return qos2_pub_cq_check(&cl_usr->qos2_rx_cq, msg_id);
dflet 0:547251f42a60 191 }
dflet 0:547251f42a60 192
dflet 0:547251f42a60 193 bool cl_mgmt_qos2_pub_rx_update(void *usr_cl, uint16_t msg_id)
dflet 0:547251f42a60 194 {
dflet 0:547251f42a60 195 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 196
dflet 0:547251f42a60 197 return cl_usr && (qos2_pub_rx_is_done(cl_usr, msg_id) ||
dflet 0:547251f42a60 198 qos2_pub_rx_logup(cl_usr, msg_id));
dflet 0:547251f42a60 199 }
dflet 0:547251f42a60 200
dflet 0:547251f42a60 201 static void ack2_msg_id_dispatch(struct client_usr *cl_usr)
dflet 0:547251f42a60 202 {
dflet 0:547251f42a60 203 struct pub_qos2_cq *tx_cq = &cl_usr->qos2_tx_cq;
dflet 0:547251f42a60 204 uint8_t rd_idx = tx_cq->rd_idx;
dflet 0:547251f42a60 205 uint8_t n_free = tx_cq->n_free;
dflet 0:547251f42a60 206 uint8_t i = 0;
dflet 0:547251f42a60 207
dflet 0:547251f42a60 208 for(i = rd_idx; i < (MAX_PUBREL_INFLT - n_free); i++) {
dflet 0:547251f42a60 209 if(mqtt_vh_msg_send(cl_usr->ctx, MQTT_PUBREL, MQTT_QOS1,
dflet 0:547251f42a60 210 true, tx_cq->id_vec[i]) <= 0)
dflet 0:547251f42a60 211 break;
dflet 0:547251f42a60 212 }
dflet 0:547251f42a60 213
dflet 0:547251f42a60 214 return;
dflet 0:547251f42a60 215 }
dflet 0:547251f42a60 216
dflet 0:547251f42a60 217 static void ack2_msg_id_purge(struct client_usr *cl_usr)
dflet 0:547251f42a60 218 {
dflet 0:547251f42a60 219 qos2_pub_cq_reset(&cl_usr->qos2_tx_cq);
dflet 0:547251f42a60 220 qos2_pub_cq_reset(&cl_usr->qos2_rx_cq);
dflet 0:547251f42a60 221 }
dflet 0:547251f42a60 222
dflet 0:547251f42a60 223 /*
dflet 0:547251f42a60 224
dflet 0:547251f42a60 225 */
dflet 0:547251f42a60 226 static struct mqtt_ack_wlist wl_qos_ack1 = {NULL, NULL};
dflet 0:547251f42a60 227 static struct mqtt_ack_wlist *qos_ack1_wl = &wl_qos_ack1;
dflet 0:547251f42a60 228
dflet 0:547251f42a60 229 /*
dflet 0:547251f42a60 230
dflet 0:547251f42a60 231 */
dflet 0:547251f42a60 232 static struct mqtt_ack_wlist wl_mqp_sess = {NULL, NULL};
dflet 0:547251f42a60 233 static struct mqtt_ack_wlist *sess_mqp_wl = &wl_mqp_sess;
dflet 0:547251f42a60 234
dflet 0:547251f42a60 235 #define MQP_CL_MAP_GET(mqp) (mqp->private_)
dflet 0:547251f42a60 236 #define MQP_CL_MAP_SET(mqp, cl_map) (mqp->private_ |= cl_map)
dflet 0:547251f42a60 237 #define MQP_CL_MAP_CLR(mqp, cl_map) (mqp->private_ &= ~cl_map)
dflet 0:547251f42a60 238
dflet 0:547251f42a60 239 #define CL_BMAP(cl_usr) (1 << cl_usr->index)
dflet 0:547251f42a60 240
dflet 0:547251f42a60 241 static inline
dflet 0:547251f42a60 242 int32_t _pub_dispatch(struct client_usr *cl_usr, struct mqtt_packet *mqp,
dflet 0:547251f42a60 243 bool dup)
dflet 0:547251f42a60 244 {
dflet 0:547251f42a60 245 /* Error, if any, is handled in 'cl_net_close()' ....*/
dflet 0:547251f42a60 246 return mqtt_server_pub_dispatch(cl_usr->ctx, mqp, dup);
dflet 0:547251f42a60 247 }
dflet 0:547251f42a60 248
dflet 0:547251f42a60 249 static void ack1_wl_mqp_dispatch(struct client_usr *cl_usr)
dflet 0:547251f42a60 250 {
dflet 0:547251f42a60 251 struct mqtt_packet *mqp = NULL;
dflet 0:547251f42a60 252
dflet 0:547251f42a60 253 for(mqp = qos_ack1_wl->head; NULL != mqp; mqp = mqp->next)
dflet 0:547251f42a60 254 if(MQP_CL_MAP_GET(mqp) & CL_BMAP(cl_usr))
dflet 0:547251f42a60 255 _pub_dispatch(cl_usr, mqp, true);
dflet 0:547251f42a60 256 }
dflet 0:547251f42a60 257
dflet 0:547251f42a60 258 #if 0
dflet 0:547251f42a60 259 static struct client_usr *find_cl_usr(uint32_t index)
dflet 0:547251f42a60 260 {
dflet 0:547251f42a60 261 struct client_usr *cl_usr = users + 0;
dflet 0:547251f42a60 262
dflet 0:547251f42a60 263 int32_t i = 0;
dflet 0:547251f42a60 264 for(i = 0; i < MAX_CLIENTS; i++, cl_usr++) {
dflet 0:547251f42a60 265 if(index == cl_usr->index)
dflet 0:547251f42a60 266 break;
dflet 0:547251f42a60 267 }
dflet 0:547251f42a60 268
dflet 0:547251f42a60 269 return (MAX_CLIENTS == i)? NULL : cl_usr;
dflet 0:547251f42a60 270 }
dflet 0:547251f42a60 271 #endif
dflet 0:547251f42a60 272
dflet 0:547251f42a60 273 #define IS_CL_USR_FREE(cl_usr) (( 0 == cl_usr->flags) && \
dflet 0:547251f42a60 274 ('\0' == cl_usr->client_id[0]))
dflet 0:547251f42a60 275
dflet 0:547251f42a60 276 #define IS_CL_INACTIVE(cl_usr) (( 0 == cl_usr->flags) && \
dflet 0:547251f42a60 277 ('\0' != cl_usr->client_id[0]))
dflet 0:547251f42a60 278
dflet 0:547251f42a60 279 #define NEED_TO_WAIT_LIST_PUBLISH(qos, cl_usr) \
dflet 0:547251f42a60 280 ((((MQTT_QOS1 == qos) && has_clean_session(cl_usr)) || \
dflet 0:547251f42a60 281 ((MQTT_QOS0 == qos)))? \
dflet 0:547251f42a60 282 false : true)
dflet 0:547251f42a60 283
dflet 0:547251f42a60 284 static inline uint32_t _cl_bmap_get(void *usr_cl)
dflet 0:547251f42a60 285 {
dflet 0:547251f42a60 286 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 287
dflet 0:547251f42a60 288 return IS_CL_USR_FREE(cl_usr)? 0 : CL_BMAP(cl_usr);
dflet 0:547251f42a60 289 }
dflet 0:547251f42a60 290
dflet 0:547251f42a60 291 uint32_t cl_bmap_get(void *usr_cl)
dflet 0:547251f42a60 292 {
dflet 0:547251f42a60 293 return usr_cl? _cl_bmap_get(usr_cl) : 0;
dflet 0:547251f42a60 294 }
dflet 0:547251f42a60 295
dflet 0:547251f42a60 296 void *cl_app_hndl_get(void *usr_cl)
dflet 0:547251f42a60 297 {
dflet 0:547251f42a60 298 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 299
dflet 0:547251f42a60 300 return (cl_usr && is_connected((client_usr*) usr_cl))? cl_usr->app : NULL;
dflet 0:547251f42a60 301 }
dflet 0:547251f42a60 302
dflet 0:547251f42a60 303 void *cl_will_hndl_get(void *usr_cl)
dflet 0:547251f42a60 304 {
dflet 0:547251f42a60 305 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 306
dflet 0:547251f42a60 307 return (cl_usr && is_connected((client_usr*)usr_cl))? cl_usr->will : NULL;
dflet 0:547251f42a60 308 }
dflet 0:547251f42a60 309
dflet 0:547251f42a60 310 static void pub_dispatch(uint32_t cl_map, struct mqtt_packet *mqp)
dflet 0:547251f42a60 311 {
dflet 0:547251f42a60 312 //uint32_t n_bits = sizeof(uint32_t) << 3; /* Multiply by 8 */
dflet 0:547251f42a60 313 uint32_t sp_map = 0; /* client Map for sessions present */
dflet 0:547251f42a60 314 enum mqtt_qos qos = ENUM_QOS(mqp->fh_byte1);/* QOS */
dflet 0:547251f42a60 315 const uint32_t cl_ref = cl_map; /* Keep ref to original */
dflet 0:547251f42a60 316
dflet 0:547251f42a60 317 int32_t i = 0;
dflet 0:547251f42a60 318 for(i = 0; i < MAX_CLIENTS; i++) {
dflet 0:547251f42a60 319 if(cl_map & (1 << i)) {
dflet 0:547251f42a60 320 struct client_usr *cl_usr = users + i; //find_cl_usr(i);
dflet 0:547251f42a60 321 if(is_connected(cl_usr))
dflet 0:547251f42a60 322 if((_pub_dispatch(cl_usr, mqp, false) > 0) &&
dflet 0:547251f42a60 323 NEED_TO_WAIT_LIST_PUBLISH(qos, cl_usr))
dflet 0:547251f42a60 324 continue;/* Processing done; next CL */
dflet 0:547251f42a60 325
dflet 0:547251f42a60 326 /* CL: unconnected / PUB Err / QOS1 PKT (clean sess) */
dflet 0:547251f42a60 327 cl_map &= ~(1 << i);
dflet 0:547251f42a60 328
dflet 0:547251f42a60 329 if(IS_CL_INACTIVE(cl_usr))
dflet 0:547251f42a60 330 sp_map |= (1 << i); /* CL: Maintain session */
dflet 0:547251f42a60 331 }
dflet 0:547251f42a60 332 }
dflet 0:547251f42a60 333
dflet 0:547251f42a60 334 if(sp_map) {
dflet 0:547251f42a60 335 struct mqtt_packet *cpy = mqp_server_copy(mqp); /* Make copy */
dflet 0:547251f42a60 336 if(cpy) {
dflet 0:547251f42a60 337 MQP_CL_MAP_SET(cpy, sp_map);
dflet 0:547251f42a60 338 mqp_ack_wlist_append(sess_mqp_wl, cpy);
dflet 0:547251f42a60 339 } else
dflet 0:547251f42a60 340 sp_map = 0;
dflet 0:547251f42a60 341 }
dflet 0:547251f42a60 342
dflet 0:547251f42a60 343 if(cl_map) { /* Wait List Publish */
dflet 0:547251f42a60 344 MQP_CL_MAP_SET(mqp, cl_map);
dflet 0:547251f42a60 345 mqp_ack_wlist_append(qos_ack1_wl, mqp);
dflet 0:547251f42a60 346 } else
dflet 0:547251f42a60 347 mqp_free(mqp); /* PUB MQP now has no more use; must be freed */
dflet 0:547251f42a60 348
dflet 0:547251f42a60 349 USR_INFO("PUBLISH: CL Map(0x%08x): For Ack 0x%08x, Inactive 0x%08x\n\r",
dflet 0:547251f42a60 350 cl_ref, cl_map, sp_map);
dflet 0:547251f42a60 351
dflet 0:547251f42a60 352 return;
dflet 0:547251f42a60 353 }
dflet 0:547251f42a60 354
dflet 0:547251f42a60 355 void cl_pub_dispatch(uint32_t cl_map, struct mqtt_packet *mqp)
dflet 0:547251f42a60 356 {
dflet 0:547251f42a60 357 pub_dispatch(cl_map, mqp);
dflet 0:547251f42a60 358 return;
dflet 0:547251f42a60 359 }
dflet 0:547251f42a60 360
dflet 0:547251f42a60 361 /* Move to mqtt_common.h and remove it from mqtt_client.h */
dflet 0:547251f42a60 362 static inline int32_t len_err_free_mqp(struct mqtt_packet *mqp)
dflet 0:547251f42a60 363 {
dflet 0:547251f42a60 364 mqp_free(mqp);
dflet 0:547251f42a60 365 return MQP_ERR_PKT_LEN;
dflet 0:547251f42a60 366 }
dflet 0:547251f42a60 367
dflet 0:547251f42a60 368 /* Move this to a common file */
dflet 0:547251f42a60 369 int32_t cl_pub_msg_send(void *usr_cl,
dflet 0:547251f42a60 370 const struct utf8_string *topic, const uint8_t *data_buf,
dflet 0:547251f42a60 371 uint32_t data_len, enum mqtt_qos qos, bool retain)
dflet 0:547251f42a60 372 {
dflet 0:547251f42a60 373 struct mqtt_packet *mqp = NULL;
dflet 0:547251f42a60 374
dflet 0:547251f42a60 375 if((NULL == topic) ||
dflet 0:547251f42a60 376 ((data_len > 0) && (NULL == data_buf)) ||
dflet 0:547251f42a60 377 (NULL == usr_cl))
dflet 0:547251f42a60 378 return MQP_ERR_FNPARAM;
dflet 0:547251f42a60 379
dflet 0:547251f42a60 380 mqp = mqp_server_alloc(MQTT_PUBLISH, 2 + topic->length + 2 + data_len);
dflet 0:547251f42a60 381 if(NULL == mqp)
dflet 0:547251f42a60 382 return MQP_ERR_PKT_AVL;
dflet 0:547251f42a60 383
dflet 0:547251f42a60 384 if((0 > mqp_pub_append_topic(mqp, topic, qos? mqp_new_id_server(): 0)) ||
dflet 0:547251f42a60 385 (data_len && (0 > mqp_pub_append_data(mqp, data_buf, data_len))))
dflet 0:547251f42a60 386 return len_err_free_mqp(mqp);
dflet 0:547251f42a60 387
dflet 0:547251f42a60 388 mqp_prep_fh(mqp, MAKE_FH_FLAGS(false, qos, retain));
dflet 0:547251f42a60 389
dflet 0:547251f42a60 390 pub_dispatch(_cl_bmap_get(usr_cl), mqp);
dflet 0:547251f42a60 391
dflet 0:547251f42a60 392 return MQP_CONTENT_LEN(mqp);
dflet 0:547251f42a60 393 }
dflet 0:547251f42a60 394
dflet 0:547251f42a60 395 static void wl_remove(struct mqtt_ack_wlist *list,
dflet 0:547251f42a60 396 struct mqtt_packet *prev,
dflet 0:547251f42a60 397 struct mqtt_packet *elem)
dflet 0:547251f42a60 398 {
dflet 0:547251f42a60 399 if(prev)
dflet 0:547251f42a60 400 prev->next = elem->next;
dflet 0:547251f42a60 401 else
dflet 0:547251f42a60 402 list->head = elem->next;
dflet 0:547251f42a60 403
dflet 0:547251f42a60 404 if(NULL == list->head)
dflet 0:547251f42a60 405 list->tail = NULL;
dflet 0:547251f42a60 406
dflet 0:547251f42a60 407 if(list->tail == elem)
dflet 0:547251f42a60 408 list->tail = prev;
dflet 0:547251f42a60 409
dflet 0:547251f42a60 410 return;
dflet 0:547251f42a60 411 }
dflet 0:547251f42a60 412
dflet 0:547251f42a60 413 static void sess_wl_mqp_dispatch(struct client_usr *cl_usr)
dflet 0:547251f42a60 414 {
dflet 0:547251f42a60 415 struct mqtt_packet *mqp = NULL, *prev = NULL, *next = NULL;
dflet 0:547251f42a60 416 uint32_t cl_map = CL_BMAP(cl_usr);
dflet 0:547251f42a60 417
dflet 0:547251f42a60 418 for(mqp = sess_mqp_wl->head; NULL != mqp; prev = mqp, mqp = next) {
dflet 0:547251f42a60 419 struct mqtt_packet *cpy = NULL;
dflet 0:547251f42a60 420
dflet 0:547251f42a60 421 if(0 == (MQP_CL_MAP_GET(mqp) & cl_map))
dflet 0:547251f42a60 422 continue; /* MQP & CL: no association */
dflet 0:547251f42a60 423
dflet 0:547251f42a60 424 /* MQP has associated client(s) - process it */
dflet 0:547251f42a60 425
dflet 0:547251f42a60 426 /* Dissociate this client from MQP */
dflet 0:547251f42a60 427 MQP_CL_MAP_CLR(mqp, cl_map);
dflet 0:547251f42a60 428 next = mqp->next; /* House keeping */
dflet 0:547251f42a60 429
dflet 0:547251f42a60 430 if(0 == MQP_CL_MAP_GET(mqp)) {
dflet 0:547251f42a60 431 /* MQP w/ no clients, remove from WL */
dflet 0:547251f42a60 432 wl_remove(sess_mqp_wl, prev, mqp);
dflet 0:547251f42a60 433
dflet 0:547251f42a60 434 /* Ensure correct arrangement for WL */
dflet 0:547251f42a60 435 cpy = mqp; mqp = prev;
dflet 0:547251f42a60 436 } else {
dflet 0:547251f42a60 437 /* MQP is associated w/ other clients */
dflet 0:547251f42a60 438 cpy = mqp_server_copy(mqp);
dflet 0:547251f42a60 439 if(NULL == cpy)
dflet 0:547251f42a60 440 continue;
dflet 0:547251f42a60 441 }
dflet 0:547251f42a60 442
dflet 0:547251f42a60 443 /* Got packet from session, dispatch it to CL */
dflet 0:547251f42a60 444 pub_dispatch(cl_map, cpy);
dflet 0:547251f42a60 445 }
dflet 0:547251f42a60 446
dflet 0:547251f42a60 447 return;
dflet 0:547251f42a60 448 }
dflet 0:547251f42a60 449
dflet 0:547251f42a60 450 static
dflet 0:547251f42a60 451 struct mqtt_packet *wl_mqp_unmap_find(struct mqtt_ack_wlist *wl,
dflet 0:547251f42a60 452 struct client_usr *cl_usr, uint16_t msg_id,
dflet 0:547251f42a60 453 struct mqtt_packet **prev)
dflet 0:547251f42a60 454 {
dflet 0:547251f42a60 455 struct mqtt_packet *mqp = NULL;
dflet 0:547251f42a60 456
dflet 0:547251f42a60 457 *prev = NULL;
dflet 0:547251f42a60 458 for(mqp = wl->head; NULL != mqp; *prev = mqp, mqp = mqp->next) {
dflet 0:547251f42a60 459 if(msg_id == mqp->msg_id) {
dflet 0:547251f42a60 460 /* Found a MQP whose msg_id matches with input */
dflet 0:547251f42a60 461 MQP_CL_MAP_CLR(mqp, CL_BMAP(cl_usr));
dflet 0:547251f42a60 462 return mqp;
dflet 0:547251f42a60 463 }
dflet 0:547251f42a60 464 }
dflet 0:547251f42a60 465
dflet 0:547251f42a60 466 return NULL;
dflet 0:547251f42a60 467 }
dflet 0:547251f42a60 468
dflet 0:547251f42a60 469 static bool wl_rmfree_try(struct mqtt_ack_wlist *wl, struct mqtt_packet *prev,
dflet 0:547251f42a60 470 struct mqtt_packet *mqp)
dflet 0:547251f42a60 471 {
dflet 0:547251f42a60 472 if(0 == MQP_CL_MAP_GET(mqp)) {
dflet 0:547251f42a60 473 wl_remove(wl, prev, mqp);
dflet 0:547251f42a60 474 mqp_free(mqp);
dflet 0:547251f42a60 475
dflet 0:547251f42a60 476 return true;
dflet 0:547251f42a60 477 }
dflet 0:547251f42a60 478
dflet 0:547251f42a60 479 return false;
dflet 0:547251f42a60 480 }
dflet 0:547251f42a60 481
dflet 0:547251f42a60 482 static bool ack1_unmap_rmfree_try(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 483 {
dflet 0:547251f42a60 484 struct mqtt_packet *prev = NULL, *mqp = NULL;
dflet 0:547251f42a60 485
dflet 0:547251f42a60 486 if(false == has_clean_session(cl_usr)) {
dflet 0:547251f42a60 487 mqp = wl_mqp_unmap_find(qos_ack1_wl, cl_usr, msg_id, &prev);
dflet 0:547251f42a60 488 if(mqp)
dflet 0:547251f42a60 489 wl_rmfree_try(qos_ack1_wl, prev, mqp);
dflet 0:547251f42a60 490 }
dflet 0:547251f42a60 491
dflet 0:547251f42a60 492 return true;
dflet 0:547251f42a60 493 }
dflet 0:547251f42a60 494
dflet 0:547251f42a60 495 static
dflet 0:547251f42a60 496 void wl_purge(struct mqtt_ack_wlist *wl, struct client_usr *cl_usr)
dflet 0:547251f42a60 497 {
dflet 0:547251f42a60 498 struct mqtt_packet *mqp = NULL, *prev = NULL, *next = NULL;
dflet 0:547251f42a60 499 uint32_t bmap = CL_BMAP(cl_usr);
dflet 0:547251f42a60 500
dflet 0:547251f42a60 501 for(mqp = wl->head; NULL != mqp; prev = mqp, mqp = next) {
dflet 0:547251f42a60 502 next = mqp->next;
dflet 0:547251f42a60 503
dflet 0:547251f42a60 504 /* Ideally, check should be done to see if cl_usr and mqp are
dflet 0:547251f42a60 505 associated. If yes, then the bit should be cleared. At the
dflet 0:547251f42a60 506 moment, blind clearing of the bit has been implemented and
dflet 0:547251f42a60 507 it has no side effects.
dflet 0:547251f42a60 508 */
dflet 0:547251f42a60 509 MQP_CL_MAP_CLR(mqp, bmap);
dflet 0:547251f42a60 510
dflet 0:547251f42a60 511 /* MQP with no clients has no more use, so try deleting MQP */
dflet 0:547251f42a60 512 if(wl_rmfree_try(wl, prev, mqp))
dflet 0:547251f42a60 513 mqp = prev; /* MQP deleted, prep for next iteration */
dflet 0:547251f42a60 514 }
dflet 0:547251f42a60 515
dflet 0:547251f42a60 516 return;
dflet 0:547251f42a60 517 }
dflet 0:547251f42a60 518
dflet 0:547251f42a60 519 static void ack1_wl_mqp_purge(struct client_usr *cl_usr)
dflet 0:547251f42a60 520 {
dflet 0:547251f42a60 521 wl_purge(qos_ack1_wl, cl_usr);
dflet 0:547251f42a60 522 }
dflet 0:547251f42a60 523
dflet 0:547251f42a60 524 static void sess_wl_mqp_purge(struct client_usr *cl_usr)
dflet 0:547251f42a60 525 {
dflet 0:547251f42a60 526 wl_purge(sess_mqp_wl, cl_usr);
dflet 0:547251f42a60 527 }
dflet 0:547251f42a60 528
dflet 0:547251f42a60 529 static void session_resume(struct client_usr *cl_usr)
dflet 0:547251f42a60 530 {
dflet 0:547251f42a60 531 ack1_wl_mqp_dispatch(cl_usr);
dflet 0:547251f42a60 532 ack2_msg_id_dispatch(cl_usr);
dflet 0:547251f42a60 533 sess_wl_mqp_dispatch(cl_usr);
dflet 0:547251f42a60 534 }
dflet 0:547251f42a60 535
dflet 0:547251f42a60 536 static void session_delete(struct client_usr *cl_usr)
dflet 0:547251f42a60 537 {
dflet 0:547251f42a60 538 ack1_wl_mqp_purge(cl_usr);
dflet 0:547251f42a60 539 ack2_msg_id_purge(cl_usr);
dflet 0:547251f42a60 540 sess_wl_mqp_purge(cl_usr);
dflet 0:547251f42a60 541 }
dflet 0:547251f42a60 542
dflet 0:547251f42a60 543 static bool has_session_data(struct client_usr *cl_usr)
dflet 0:547251f42a60 544 {
dflet 0:547251f42a60 545 uint32_t map = CL_BMAP(cl_usr);
dflet 0:547251f42a60 546 struct mqtt_packet *elem;
dflet 0:547251f42a60 547
dflet 0:547251f42a60 548 if(cl_usr->n_sub)
dflet 0:547251f42a60 549 return true;
dflet 0:547251f42a60 550
dflet 0:547251f42a60 551 elem = qos_ack1_wl->head;
dflet 0:547251f42a60 552 while(elem) {
dflet 0:547251f42a60 553 if(MQP_CL_MAP_GET(elem) & map)
dflet 0:547251f42a60 554 return true;
dflet 0:547251f42a60 555
dflet 0:547251f42a60 556 elem = elem->next;
dflet 0:547251f42a60 557 }
dflet 0:547251f42a60 558
dflet 0:547251f42a60 559 elem = sess_mqp_wl->head;
dflet 0:547251f42a60 560 while(elem) {
dflet 0:547251f42a60 561 if(MQP_CL_MAP_GET(elem) & map)
dflet 0:547251f42a60 562 return true;
dflet 0:547251f42a60 563
dflet 0:547251f42a60 564 elem = elem->next;
dflet 0:547251f42a60 565 }
dflet 0:547251f42a60 566
dflet 0:547251f42a60 567 return false;
dflet 0:547251f42a60 568 }
dflet 0:547251f42a60 569
dflet 0:547251f42a60 570 bool cl_can_session_delete(void *usr_cl)
dflet 0:547251f42a60 571 {
dflet 0:547251f42a60 572 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 573
dflet 0:547251f42a60 574 return cl_usr? (has_clean_session(cl_usr) ||
dflet 0:547251f42a60 575 !has_session_data(cl_usr)) : false;
dflet 0:547251f42a60 576 }
dflet 0:547251f42a60 577
dflet 0:547251f42a60 578 void cl_on_net_close(void *usr_cl)
dflet 0:547251f42a60 579 {
dflet 0:547251f42a60 580 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 581
dflet 0:547251f42a60 582 if(is_assigned(cl_usr)) {
dflet 0:547251f42a60 583 if(false == has_session_data(cl_usr))
dflet 0:547251f42a60 584 cl_usr_free(cl_usr);
dflet 0:547251f42a60 585 } else if(has_clean_session(cl_usr)) {
dflet 0:547251f42a60 586 session_delete(cl_usr);
dflet 0:547251f42a60 587 cl_usr_free(cl_usr);
dflet 0:547251f42a60 588 } else {
dflet 0:547251f42a60 589 set_connect_state(cl_usr, false);
dflet 0:547251f42a60 590 cl_usr->ctx = NULL;
dflet 0:547251f42a60 591 cl_usr->app = NULL;
dflet 0:547251f42a60 592 }
dflet 0:547251f42a60 593
dflet 0:547251f42a60 594 return;
dflet 0:547251f42a60 595 }
dflet 0:547251f42a60 596
dflet 0:547251f42a60 597 static bool proc_pub_rel_rx(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 598 {
dflet 0:547251f42a60 599 mqtt_vh_msg_send(cl_usr->ctx, MQTT_PUBCOMP,
dflet 0:547251f42a60 600 MQTT_QOS0, true, msg_id);
dflet 0:547251f42a60 601
dflet 0:547251f42a60 602 if(qos2_pub_rx_is_done(cl_usr, msg_id))
dflet 0:547251f42a60 603 qos2_pub_rx_unlog(cl_usr, msg_id);
dflet 0:547251f42a60 604
dflet 0:547251f42a60 605 return true;
dflet 0:547251f42a60 606 }
dflet 0:547251f42a60 607
dflet 0:547251f42a60 608 static bool proc_pub_rec_rx(struct client_usr *cl_usr, uint16_t msg_id)
dflet 0:547251f42a60 609 {
dflet 0:547251f42a60 610 struct mqtt_packet *prev = NULL, *mqp = NULL;
dflet 0:547251f42a60 611
dflet 0:547251f42a60 612 mqp = wl_mqp_unmap_find(qos_ack1_wl, cl_usr, msg_id, &prev);
dflet 0:547251f42a60 613 if(mqp && ack2_msg_id_logup(cl_usr, msg_id)) {
dflet 0:547251f42a60 614
dflet 0:547251f42a60 615 wl_rmfree_try(qos_ack1_wl, prev, mqp);
dflet 0:547251f42a60 616
dflet 0:547251f42a60 617 mqtt_vh_msg_send(cl_usr->ctx, MQTT_PUBREL,
dflet 0:547251f42a60 618 MQTT_QOS1, true, msg_id);
dflet 0:547251f42a60 619
dflet 0:547251f42a60 620 return true;
dflet 0:547251f42a60 621 }
dflet 0:547251f42a60 622
dflet 0:547251f42a60 623 return false;
dflet 0:547251f42a60 624 }
dflet 0:547251f42a60 625
dflet 0:547251f42a60 626 bool cl_notify_ack(void *usr_cl, uint8_t msg_type, uint16_t msg_id)
dflet 0:547251f42a60 627 {
dflet 0:547251f42a60 628 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 629 bool rv = false;
dflet 0:547251f42a60 630
dflet 0:547251f42a60 631 if(NULL == cl_usr)
dflet 0:547251f42a60 632 return rv;
dflet 0:547251f42a60 633
dflet 0:547251f42a60 634 switch(msg_type) {
dflet 0:547251f42a60 635
dflet 0:547251f42a60 636 case MQTT_PUBACK:
dflet 0:547251f42a60 637 rv = ack1_unmap_rmfree_try(cl_usr, msg_id);
dflet 0:547251f42a60 638 break;
dflet 0:547251f42a60 639
dflet 0:547251f42a60 640 case MQTT_PUBREC:
dflet 0:547251f42a60 641 rv = proc_pub_rec_rx(cl_usr, msg_id);
dflet 0:547251f42a60 642 break;
dflet 0:547251f42a60 643
dflet 0:547251f42a60 644 case MQTT_PUBREL:
dflet 0:547251f42a60 645 rv = proc_pub_rel_rx(cl_usr, msg_id);
dflet 0:547251f42a60 646 break;
dflet 0:547251f42a60 647
dflet 0:547251f42a60 648 case MQTT_PUBCOMP:
dflet 0:547251f42a60 649 rv = ack2_msg_id_unlog(cl_usr, msg_id);
dflet 0:547251f42a60 650 break;
dflet 0:547251f42a60 651
dflet 0:547251f42a60 652 default:
dflet 0:547251f42a60 653 break;
dflet 0:547251f42a60 654 }
dflet 0:547251f42a60 655
dflet 0:547251f42a60 656 return rv;
dflet 0:547251f42a60 657 }
dflet 0:547251f42a60 658
dflet 0:547251f42a60 659 static void assign_cl_index_as_id(struct client_usr *cl_usr)
dflet 0:547251f42a60 660 {
dflet 0:547251f42a60 661 /* TBD: need a better implementation */
dflet 0:547251f42a60 662 char *client_id = cl_usr->client_id;
dflet 0:547251f42a60 663
dflet 0:547251f42a60 664 client_id[0] = 'S';
dflet 0:547251f42a60 665 client_id[1] = 'e';
dflet 0:547251f42a60 666 client_id[2] = 'l';
dflet 0:547251f42a60 667 client_id[3] = 'f';
dflet 0:547251f42a60 668 client_id[4] = '-';
dflet 0:547251f42a60 669 client_id[5] = ((cl_usr->index & 0xf0) >> 4) + 0x30;
dflet 0:547251f42a60 670 client_id[6] = ((cl_usr->index & 0x0f)) + 0x30;
dflet 0:547251f42a60 671 client_id[7] = '\0';
dflet 0:547251f42a60 672
dflet 0:547251f42a60 673 /* Make sure that above array size is with in MAX_CLIENT_ID_LEN */
dflet 0:547251f42a60 674
dflet 0:547251f42a60 675 return;
dflet 0:547251f42a60 676 }
dflet 0:547251f42a60 677
dflet 0:547251f42a60 678 static struct client_usr *assign_cl_usr(char *client_id, uint8_t *vh_buf)
dflet 0:547251f42a60 679 {
dflet 0:547251f42a60 680 struct client_usr *cl_usr, *fr_usr = NULL;
dflet 0:547251f42a60 681 int32_t idx = 0;
dflet 0:547251f42a60 682 for(idx = 0; idx < MAX_CLIENTS; idx++) {
dflet 0:547251f42a60 683 cl_usr = users + idx;
dflet 0:547251f42a60 684 if((NULL == fr_usr) && IS_CL_USR_FREE(cl_usr))
dflet 0:547251f42a60 685 fr_usr = cl_usr; /* Note 1st free cl_usr */
dflet 0:547251f42a60 686
dflet 0:547251f42a60 687 if((NULL == client_id) && (NULL != fr_usr)) {
dflet 0:547251f42a60 688 /* Free cl_usr is present to create CL-ID */
dflet 0:547251f42a60 689 break;
dflet 0:547251f42a60 690
dflet 0:547251f42a60 691 } else if((NULL != client_id) &&
dflet 0:547251f42a60 692 (0 == strncmp(cl_usr->client_id, client_id,
dflet 0:547251f42a60 693 MAX_CLIENT_ID_LEN))) {
dflet 0:547251f42a60 694 /* Found a client obj with exact ID match */
dflet 0:547251f42a60 695 if(is_connected(cl_usr)) {
dflet 0:547251f42a60 696 /* Error: CL-ID is already active */
dflet 0:547251f42a60 697 vh_buf[1] = CONNACK_RC_CLI_REJECT;
dflet 0:547251f42a60 698 cl_usr = NULL;
dflet 0:547251f42a60 699 }
dflet 0:547251f42a60 700 break;
dflet 0:547251f42a60 701 }
dflet 0:547251f42a60 702 }
dflet 0:547251f42a60 703
dflet 0:547251f42a60 704 if(idx == MAX_CLIENTS) { /* Did not find a match */
dflet 0:547251f42a60 705 cl_usr = fr_usr;
dflet 0:547251f42a60 706 if(NULL == cl_usr)
dflet 0:547251f42a60 707 /* Server Resource unavailable */
dflet 0:547251f42a60 708 vh_buf[1] = CONNACK_RC_SVR_UNAVBL;
dflet 0:547251f42a60 709 }
dflet 0:547251f42a60 710
dflet 0:547251f42a60 711 if(NULL != cl_usr) {
dflet 0:547251f42a60 712 if(NULL == client_id)
dflet 0:547251f42a60 713 assign_cl_index_as_id(cl_usr); /* Get ID */
dflet 0:547251f42a60 714 else if(IS_CL_USR_FREE(cl_usr))
dflet 0:547251f42a60 715 strncpy(cl_usr->client_id, client_id,
dflet 0:547251f42a60 716 MAX_CLIENT_ID_LEN);
dflet 0:547251f42a60 717
dflet 0:547251f42a60 718 set_assigned(cl_usr, true);
dflet 0:547251f42a60 719 }
dflet 0:547251f42a60 720
dflet 0:547251f42a60 721 USR_INFO("Assignment of cl_usr %s (detail: index %d and name %s) \n\r",
dflet 0:547251f42a60 722 cl_usr? "Succeeded" : "Failed", cl_usr? (int32_t)cl_usr->index : -1,
dflet 0:547251f42a60 723 cl_usr? cl_usr->client_id : "");
dflet 0:547251f42a60 724
dflet 0:547251f42a60 725 return cl_usr;
dflet 0:547251f42a60 726 }
dflet 0:547251f42a60 727
dflet 0:547251f42a60 728 uint16_t cl_connect_rx(void *ctx_cl, bool clean_session, char *client_id,
dflet 0:547251f42a60 729 void *app_cl, void *will, void **usr_cl)
dflet 0:547251f42a60 730 {
dflet 0:547251f42a60 731 uint8_t vh_buf[] = {0x00, CONNACK_RC_REQ_ACCEPT};
dflet 0:547251f42a60 732 struct client_usr *cl_usr;
dflet 0:547251f42a60 733
dflet 0:547251f42a60 734 if(client_id && ('\0' == client_id[0]))
dflet 0:547251f42a60 735 /* Shouldn't happen: CLIENT ID with a NUL only string */
dflet 0:547251f42a60 736 return CONNACK_RC_CLI_REJECT;
dflet 0:547251f42a60 737
dflet 0:547251f42a60 738 cl_usr = assign_cl_usr(client_id, vh_buf);
dflet 0:547251f42a60 739 if(NULL == cl_usr)
dflet 0:547251f42a60 740 return vh_buf[1]; /* Use vh_buf from assign_cl_usr() */
dflet 0:547251f42a60 741
dflet 0:547251f42a60 742 if((false == clean_session) && has_session_data(cl_usr))
dflet 0:547251f42a60 743 vh_buf[0] = 0x01; /* Set Session Present Flag */
dflet 0:547251f42a60 744
dflet 0:547251f42a60 745 #if 0
dflet 0:547251f42a60 746 if(0x00 == vh_buf[1])
dflet 0:547251f42a60 747 *usr_cl = (void*)cl_usr;
dflet 0:547251f42a60 748 #endif
dflet 0:547251f42a60 749 *usr_cl = (void*)cl_usr;
dflet 0:547251f42a60 750
dflet 0:547251f42a60 751 cl_usr->ctx = ctx_cl;
dflet 0:547251f42a60 752 cl_usr->app = app_cl;
dflet 0:547251f42a60 753 cl_usr->will = will;
dflet 0:547251f42a60 754
dflet 0:547251f42a60 755 return ((vh_buf[0] << 8) | vh_buf[1]);
dflet 0:547251f42a60 756 }
dflet 0:547251f42a60 757
dflet 0:547251f42a60 758 void cl_on_connack_send(void *usr_cl, bool clean_session)
dflet 0:547251f42a60 759 {
dflet 0:547251f42a60 760 struct client_usr *cl_usr = (struct client_usr*) usr_cl;
dflet 0:547251f42a60 761
dflet 0:547251f42a60 762 if(false == is_assigned(cl_usr)) {
dflet 0:547251f42a60 763 USR_INFO("Fatal: CONNACK for unassigned cl_usr Id %u, abort\n\r",
dflet 0:547251f42a60 764 cl_usr->index);
dflet 0:547251f42a60 765 return;
dflet 0:547251f42a60 766 }
dflet 0:547251f42a60 767
dflet 0:547251f42a60 768 set_assigned(cl_usr, false);
dflet 0:547251f42a60 769 set_clean_session(cl_usr, clean_session);
dflet 0:547251f42a60 770 set_connect_state(cl_usr, true);
dflet 0:547251f42a60 771
dflet 0:547251f42a60 772 if(clean_session) {
dflet 0:547251f42a60 773 session_delete(cl_usr);
dflet 0:547251f42a60 774 } else {
dflet 0:547251f42a60 775 session_resume(cl_usr);
dflet 0:547251f42a60 776 }
dflet 0:547251f42a60 777
dflet 0:547251f42a60 778 DBG_INFO("Server is now connected to client %s\n\r", cl_usr->client_id);
dflet 0:547251f42a60 779
dflet 0:547251f42a60 780 return;
dflet 0:547251f42a60 781 }
dflet 0:547251f42a60 782
dflet 0:547251f42a60 783 int32_t cl_mgmt_init(void)
dflet 0:547251f42a60 784 {
dflet 0:547251f42a60 785 cl_usr_init();
dflet 0:547251f42a60 786
dflet 0:547251f42a60 787 return 0;
dflet 0:547251f42a60 788 }
dflet 0:547251f42a60 789
dflet 0:547251f42a60 790 }//namespace mbed_mqtt