Annotation of mqtt/src/conn.c, revision 1.1.2.13
1.1.2.1 misho 1: #include "global.h"
2:
3:
4: /* ------------------------------------------------------------------- */
5:
6: /*
7: * mqtt_msgCONNECT() Create CONNECT message
8: *
9: * @buf = Message buffer
10: * @csConnID = ConnectID
11: * @csUser = Username if !=NULL
12: * @csPass = Password for Username, only if csUser is set
13: * @csWillTopic = Will Topic if !=NULL Will Flags set into message
14: * @csWillMessage = Will Message, may be NULL
15: * @ClrSess = Clear Session subscriptions after disconnect
16: * @WillQOS = Will QOS if csWillTopic is set
17: * @WillRetain = Will Retain Will Message if csWillTopic is set
18: * return: -1 error or >-1 message size for send
19: */
20: int
21: mqtt_msgCONNECT(mqtt_msg_t * __restrict buf, const char *csConnID,
22: const char *csUser, const char *csPass,
23: const char *csWillTopic, const char *csWillMessage,
1.1.2.3 misho 24: u_char ClrSess, u_char WillQOS, u_char WillRetain)
1.1.2.1 misho 25: {
26: int siz = 0;
27: struct mqtthdr *hdr;
28: mqtthdr_var_t *var, *cid, *topic, *wmsg, *user, *pass;
29: mqtthdr_protover_t *proto;
30: mqtthdr_connflgs_t *flags;
31: mqtt_v_t *ka;
32:
33: if (!buf || !csConnID)
34: return -1;
1.1.2.10 misho 35: if (strlen(csConnID) > 24) {
1.1.2.1 misho 36: mqtt_SetErr(EINVAL, "Error:: invalid argument ConnID is too long (max 23 bytes)");
37: return -1;
38: }
1.1.2.10 misho 39: if (csUser && strlen(csUser) > 13) {
1.1.2.1 misho 40: mqtt_SetErr(EINVAL, "Error:: invalid argument Username is too long (max 12 bytes)");
41: return -1;
42: }
1.1.2.10 misho 43: if (csPass && strlen(csPass) > 13) {
1.1.2.1 misho 44: mqtt_SetErr(EINVAL, "Error:: invalid argument Password is too long (max 12 bytes)");
45: return -1;
46: }
1.1.2.3 misho 47: if (WillQOS > MQTT_QOS_EXACTLY) {
1.1.2.1 misho 48: mqtt_SetErr(EINVAL, "Error:: invalid argument WillQOS - unknown QOS value");
49: return -1;
50: }
51:
52: if (mqtt_msgRealloc(buf, BUFSIZ) == -1)
53: return -1;
54: else {
55: hdr = (struct mqtthdr *) (buf->msg_base + siz);
1.1.2.2 misho 56: siz += sizeof(struct mqtthdr);
1.1.2.1 misho 57: var = (mqtthdr_var_t*) (buf->msg_base + siz);
58: siz += 8;
59: proto = buf->msg_base + siz;
60: siz++;
61: flags = (mqtthdr_connflgs_t*) (buf->msg_base + siz);
62: siz++;
63: ka = (mqtt_v_t*) (buf->msg_base + siz);
64: siz += sizeof(mqtt_v_t);
65: }
66:
67: /* fixed header */
1.1.2.4 misho 68: MQTTHDR_MSGINIT(hdr);
1.1.2.1 misho 69: hdr->mqtt_msg.type = MQTT_TYPE_CONNECT;
70: *hdr->mqtt_len = 0;
71:
72: /* variable header */
73: var->var_sb.sb.l = 6;
74: memcpy(var->var_data, MQTT_CONN_STR, 6);
75:
76: *proto = MQTT_PROTO_VER;
77:
78: /* CONNECT header */
79: flags->clean_sess = ClrSess ? 1 : 0;
80: if (csUser) {
81: flags->username = 1;
82: flags->password = csPass ? 1 : 0;
83: } else {
84: flags->username = 0;
85: flags->password = 0;
86: }
87: if (csWillTopic) {
88: flags->will_flg = 1;
89: flags->will_qos = WillQOS;
90: flags->will_retain = WillRetain ? 1 : 0;
91: } else {
92: flags->will_flg = 0;
93: flags->will_qos = 0;
94: flags->will_retain = 0;
95: }
96:
97: ka->sb.l = MQTT_KEEPALIVE;
98:
99: /* ConnID */
100: cid = (mqtthdr_var_t*) (buf->msg_base + siz);
101: cid->var_sb.val = htons(strlen(csConnID));
102: siz += MQTTHDR_VAR_SIZEOF(cid);
103: memcpy(cid->var_data, csConnID, ntohs(cid->var_sb.val));
104:
105: /* If Will Flags setup */
106: if (csWillTopic) {
107: topic = (mqtthdr_var_t*) (buf->msg_base + siz);
108: topic->var_sb.val = htons(strlen(csWillTopic));
109: memcpy(topic->var_data, csWillTopic, ntohs(topic->var_sb.val));
110: siz += MQTTHDR_VAR_SIZEOF(topic);
111:
112: wmsg = (mqtthdr_var_t*) (buf->msg_base + siz);
113: if (csWillMessage) {
114: wmsg->var_sb.val = htons(strlen(csWillMessage));
115: memcpy(wmsg->var_data, csWillMessage, ntohs(wmsg->var_sb.val));
116: } else
117: wmsg->var_sb.val = 0;
118: siz += MQTTHDR_VAR_SIZEOF(wmsg);
119: }
120:
121: /* If defined Username & Password */
122: if (csUser) {
123: user = (mqtthdr_var_t*) (buf->msg_base + siz);
124: user->var_sb.val = htons(strlen(csUser));
125: memcpy(user->var_data, csUser, ntohs(user->var_sb.val));
126: siz += MQTTHDR_VAR_SIZEOF(user);
127:
128: if (csPass) {
129: pass = (mqtthdr_var_t*) (buf->msg_base + siz);
130: pass->var_sb.val = htons(strlen(csPass));
131: memcpy(pass->var_data, csPass, ntohs(pass->var_sb.val));
132: siz += MQTTHDR_VAR_SIZEOF(pass);
133: }
134: }
135:
1.1.2.3 misho 136: *hdr->mqtt_len = mqtt_encodeLen(siz - sizeof(struct mqtthdr));
1.1.2.1 misho 137: mqtt_msgRealloc(buf, siz);
138: return siz;
139: }
1.1.2.2 misho 140:
141: /*
142: * mqtt_msgCONNACK() Create CONNACK message
143: *
144: * @buf = Message buffer
145: * @retcode = Return code
146: * return: -1 error or >-1 message size for send
147: */
148: int
149: mqtt_msgCONNACK(mqtt_msg_t * __restrict buf, u_char retcode)
150: {
151: int siz = 0;
152: struct mqtthdr *hdr;
153: mqtthdr_connack_t *ack;
154:
155: if (!buf)
156: return -1;
157: if (retcode > MQTT_RETCODE_DENIED) {
158: mqtt_SetErr(EINVAL, "Error:: invalid retcode");
159: return -1;
160: }
161:
162: if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr) + sizeof(mqtthdr_connack_t)) == -1)
163: return -1;
164: else {
165: hdr = (struct mqtthdr *) (buf->msg_base + siz);
166: siz += sizeof(struct mqtthdr);
167: ack = (mqtthdr_connack_t*) (buf->msg_base + siz);
168: siz += sizeof(mqtthdr_connack_t);
169: }
170:
171: /* fixed header */
1.1.2.4 misho 172: MQTTHDR_MSGINIT(hdr);
1.1.2.2 misho 173: hdr->mqtt_msg.type = MQTT_TYPE_CONNACK;
174: *hdr->mqtt_len = sizeof(mqtthdr_connack_t);
175:
176: /* CONNACK header */
177: ack->reserved = 0;
178: ack->retcode = retcode;
179:
180: return siz;
181: }
1.1.2.5 misho 182:
183: static int
184: _mqtt_msgSIMPLE_(mqtt_msg_t * __restrict buf, u_char cmd)
185: {
186: int siz = 0;
187: struct mqtthdr *hdr;
188:
189: if (!buf)
190: return -1;
191:
192: if (mqtt_msgRealloc(buf, sizeof(struct mqtthdr)) == -1)
193: return -1;
194: else {
195: hdr = (struct mqtthdr *) (buf->msg_base + siz);
196: siz += sizeof(struct mqtthdr);
197: }
198:
199: /* fixed header */
200: MQTTHDR_MSGINIT(hdr);
201: hdr->mqtt_msg.type = cmd;
202: *hdr->mqtt_len = 0;
203:
204: return siz;
205: }
206:
207: /*
208: * mqtt_msgPINGREQ() Create PINGREQ message
209: *
210: * @buf = Message buffer
211: * return: -1 error or >-1 message size for send
212: */
213: int
214: mqtt_msgPINGREQ(mqtt_msg_t * __restrict buf)
215: {
216: return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_PINGREQ);
217: }
218:
219: /*
220: * mqtt_msgPINGRESP() Create PINGRESP message
221: *
222: * @buf = Message buffer
223: * return: -1 error or >-1 message size for send
224: */
225: int
226: mqtt_msgPINGRESP(mqtt_msg_t * __restrict buf)
227: {
228: return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_PINGRESP);
229: }
230:
231: /*
232: * mqtt_msgDISCONNECT() Create DISCONNECT message
233: *
234: * @buf = Message buffer
235: * return: -1 error or >-1 message size for send
236: */
237: int
238: mqtt_msgDISCONNECT(mqtt_msg_t * __restrict buf)
239: {
240: return _mqtt_msgSIMPLE_(buf, MQTT_TYPE_DISCONNECT);
241: }
1.1.2.6 misho 242:
243: /* ============= decode ============ */
244:
245: /*
246: * mqtt_readCONNECT() Read elements from CONNECT message
247: *
248: * @buf = Message buffer
249: * @kasec = Keep Alive in seconds for current connection
250: * @psConnID = ConnectID
251: * @connLen = ConnectID length
252: * @psUser = Username if !=NULL
253: * @userLen = Username length
254: * @psPass = Password for Username, only if csUser is set
255: * @passLen = Password length
1.1.2.11 misho 256: * @psWillTopic = Will Topic if !=NULL Will Flags set into message and must be free()
257: * @psWillMessage = Will Message, may be NULL if !NULL must be free() after use!
1.1.2.6 misho 258: * return: .reserved == 1 is error or == 0 connection flags & msg ok
259: */
1.1.2.12 misho 260: mqtthdr_connack_t
1.1.2.6 misho 261: mqtt_readCONNECT(mqtt_msg_t * __restrict buf, u_short *kasec, char * __restrict psConnID, int connLen,
262: char * __restrict psUser, int userLen, char * __restrict psPass, int passLen,
1.1.2.10 misho 263: char ** __restrict psWillTopic, char ** __restrict psWillMessage)
1.1.2.6 misho 264: {
1.1.2.12 misho 265: mqtthdr_connflgs_t flg = { MQTT_CONNFLGS_INIT };
266: mqtthdr_connack_t cack = { 1, MQTT_RETCODE_DENIED };
1.1.2.6 misho 267: struct mqtthdr *hdr;
268: mqtthdr_var_t *var;
269: mqtt_v_t *ka;
270: mqtthdr_protover_t *proto;
271: int len, ret;
272: caddr_t pos;
273:
274: if (!buf || !buf->msg_base || !buf->msg_len || !psConnID || !connLen)
1.1.2.12 misho 275: return cack;
1.1.2.6 misho 276:
1.1.2.8 misho 277: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNECT, &ret, &len);
278: if (!hdr)
1.1.2.12 misho 279: return cack;
1.1.2.6 misho 280: if (len < 12) {
281: mqtt_SetErr(EINVAL, "Error:: short message length %d", len);
1.1.2.12 misho 282: return cack;
1.1.2.6 misho 283: } else {
284: pos = buf->msg_base + ret + 1;
285: var = (mqtthdr_var_t*) pos;
286: }
287: /* check init string & protocol */
1.1.2.13! misho 288: if (var->var_sb.sb.l != 6 || strncmp((char*) var->var_data, MQTT_CONN_STR, 6)) {
1.1.2.6 misho 289: mqtt_SetErr(EINVAL, "Error:: invalid init string %.6s(%d)",
290: var->var_data, var->var_sb.sb.l);
1.1.2.12 misho 291: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
292: return cack;
1.1.2.6 misho 293: } else {
294: pos += var->var_sb.sb.l + sizeof(mqtt_v_t);
295: proto = (mqtthdr_protover_t*) pos;
296: }
297: if (*proto != MQTT_PROTO_VER) {
298: mqtt_SetErr(EINVAL, "Error:: invalid protocol version %d", *pos);
1.1.2.12 misho 299: cack.retcode = MQTT_RETCODE_REFUSE_VER;
300: return cack;
1.1.2.6 misho 301: } else
302: pos++;
303: flg = *(mqtthdr_connflgs_t*) pos;
304: pos++;
305: ka = (mqtt_v_t*) pos;
306: *kasec = ntohs(ka->val);
307: pos += sizeof(mqtt_v_t);
308:
309: len -= pos - (caddr_t) var;
310:
311: /* get ConnID */
312: var = (mqtthdr_var_t*) pos;
313: len -= MQTTHDR_VAR_SIZEOF(var);
314: if (len < 0) {
315: mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Connection ID %d", len);
1.1.2.12 misho 316: cack.retcode = MQTT_RETCODE_REFUSE_ID;
317: return cack;
1.1.2.6 misho 318: } else {
319: memset(psConnID, 0, connLen--);
320: memcpy(psConnID, var->var_data, ntohs(var->var_sb.val) > connLen ? connLen : ntohs(var->var_sb.val));
321: pos += MQTTHDR_VAR_SIZEOF(var);
322: }
323:
324: /* get Willz */
325: if (flg.will_flg) {
326: var = (mqtthdr_var_t*) pos;
327: len -= MQTTHDR_VAR_SIZEOF(var);
328: if (len < 0) {
329: mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Topic %d", len);
1.1.2.12 misho 330: cack.retcode = MQTT_RETCODE_REFUSE_ID;
331: return cack;
1.1.2.6 misho 332: } else {
1.1.2.10 misho 333: if (psWillTopic) {
334: *psWillTopic = malloc(ntohs(var->var_sb.val) + 1);
335: if (!*psWillTopic) {
336: LOGERR;
1.1.2.12 misho 337: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
338: return cack;
1.1.2.10 misho 339: } else
340: memset(*psWillTopic, 0, ntohs(var->var_sb.val) + 1);
341: memcpy(*psWillTopic, var->var_data, ntohs(var->var_sb.val));
1.1.2.6 misho 342: }
343: pos += MQTTHDR_VAR_SIZEOF(var);
344: }
345:
346: var = (mqtthdr_var_t*) pos;
347: len -= MQTTHDR_VAR_SIZEOF(var);
348: if (len < 0) {
349: mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Will Message %d", len);
1.1.2.12 misho 350: cack.retcode = MQTT_RETCODE_REFUSE_ID;
351: return cack;
1.1.2.6 misho 352: } else {
1.1.2.10 misho 353: if (psWillMessage) {
354: *psWillMessage = malloc(ntohs(var->var_sb.val) + 1);
355: if (!*psWillMessage) {
356: LOGERR;
1.1.2.12 misho 357: cack.retcode = MQTT_RETCODE_REFUSE_UNAVAIL;
358: return cack;
1.1.2.10 misho 359: } else
360: memset(*psWillMessage, 0, ntohs(var->var_sb.val) + 1);
361: memcpy(*psWillMessage, var->var_data, ntohs(var->var_sb.val));
1.1.2.6 misho 362: }
363: pos += MQTTHDR_VAR_SIZEOF(var);
364: }
365: }
366:
367: /* get User/Pass */
368: if (flg.username) {
369: var = (mqtthdr_var_t*) pos;
370: len -= MQTTHDR_VAR_SIZEOF(var);
371: if (len < 0) {
372: mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Username %d", len);
1.1.2.12 misho 373: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
374: return cack;
1.1.2.6 misho 375: } else {
376: if (psUser && userLen) {
377: memset(psUser, 0, userLen--);
378: memcpy(psUser, var->var_data,
379: ntohs(var->var_sb.val) > userLen ? userLen : ntohs(var->var_sb.val));
380: }
381: pos += MQTTHDR_VAR_SIZEOF(var);
382: }
383: }
384: if (flg.password) {
385: var = (mqtthdr_var_t*) pos;
386: len -= MQTTHDR_VAR_SIZEOF(var);
387: if (len < 0) {
388: mqtt_SetErr(EINVAL, "Error:: unexpected EOM at Password %d", len);
1.1.2.12 misho 389: cack.retcode = MQTT_RETCODE_REFUSE_USERPASS;
390: return cack;
1.1.2.6 misho 391: } else {
392: if (psPass && passLen) {
393: memset(psPass, 0, passLen--);
394: memcpy(psPass, var->var_data,
395: ntohs(var->var_sb.val) > passLen ? passLen : ntohs(var->var_sb.val));
396: }
397: pos += MQTTHDR_VAR_SIZEOF(var);
398: }
399: }
400:
1.1.2.12 misho 401: flg.reserved = 0;
402: cack.reserved = flg.flags;
403: cack.retcode = MQTT_RETCODE_ACCEPTED;
404: return cack;
1.1.2.6 misho 405: }
1.1.2.7 misho 406:
407: /*
408: * mqtt_readCONNACK() Read CONNACK message
409: *
410: * @buf = Message buffer
411: * return: -1 error or >-1 CONNECT message return code
412: */
413: u_char
414: mqtt_readCONNACK(mqtt_msg_t * __restrict buf)
415: {
416: int len, ret;
417: struct mqtthdr *hdr;
418: mqtthdr_connack_t *ack;
419: caddr_t pos;
420:
421: if (!buf || !buf->msg_base || !buf->msg_len)
422: return (u_char) -1;
423:
1.1.2.8 misho 424: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_CONNACK, &ret, &len);
425: if (!hdr)
1.1.2.7 misho 426: return (u_char) -1;
427: if (len < sizeof(mqtthdr_connack_t)) {
428: mqtt_SetErr(EINVAL, "Error:: short message length %d", len);
429: return (u_char) -1;
430: } else {
431: pos = buf->msg_base + ret + 1;
432: ack = (mqtthdr_connack_t*) pos;
433: }
434:
435: if (ack->retcode > MQTT_RETCODE_DENIED) {
436: mqtt_SetErr(EINVAL, "Error:: invalid retcode %u", ack->retcode);
437: return (u_char) -1;
438: }
439:
440: return ack->retcode;
441: }
1.1.2.9 misho 442:
443: /*
444: * mqtt_readDISCONNECT() Read DISCONNECT message
445: *
446: * @buf = Message buffer
447: * return: -1 error, 0 ok, >0 undefined result
448: */
449: int
450: mqtt_readDISCONNECT(mqtt_msg_t * __restrict buf)
451: {
452: int len, ret;
453: struct mqtthdr *hdr;
454:
455: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_DISCONNECT, &ret, &len);
456: if (!hdr || ret != 1)
457: return -1;
458:
459: return len;
460: }
461:
462: /*
463: * mqtt_readPINGREQ() Read PINGREQ message
464: *
465: * @buf = Message buffer
466: * return: -1 error, 0 ok, >0 undefined result
467: */
468: int
469: mqtt_readPINGREQ(mqtt_msg_t * __restrict buf)
470: {
471: int len, ret;
472: struct mqtthdr *hdr;
473:
474: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGREQ, &ret, &len);
475: if (!hdr || ret != 1)
476: return -1;
477:
478: return len;
479: }
480:
481: /*
482: * mqtt_readPINGRESP() Read PINGRESP message
483: *
484: * @buf = Message buffer
485: * return: -1 error, 0 ok, >0 undefined result
486: */
487: int
488: mqtt_readPINGRESP(mqtt_msg_t * __restrict buf)
489: {
490: int len, ret;
491: struct mqtthdr *hdr;
492:
493: hdr = _mqtt_readHEADER(buf, MQTT_TYPE_PINGRESP, &ret, &len);
494: if (!hdr || ret != 1)
495: return -1;
496:
497: return len;
498: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>