Part of TI's mqtt
Dependents: mqtt_V1 cc3100_Test_mqtt_CM3
client_mgmt.cpp@0:547251f42a60, 2015-06-06 (annotated)
- Committer:
- dflet
- Date:
- Sat Jun 06 13:29:08 2015 +0000
- Revision:
- 0:547251f42a60
Part of mqtt_V1
Who changed what in which revision?
User | Revision | Line number | New 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 |