Basic C library for MQTT packet serialization and deserialization
Dependents: MQTT MQTT MQTT MQTT ... more
Fork of MQTTPacket by
MQTTConnectClient.c
00001 /******************************************************************************* 00002 * Copyright (c) 2014 IBM Corp. 00003 * 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * and the Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * Ian Craggs - initial API and implementation and/or initial documentation 00015 *******************************************************************************/ 00016 00017 #include "MQTTPacket.h" 00018 #include "StackTrace.h" 00019 00020 #include <string.h> 00021 00022 /** 00023 * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. 00024 * @param options the options to be used to build the connect packet 00025 * @return the length of buffer needed to contain the serialized version of the packet 00026 */ 00027 int MQTTSerialize_connectLength(MQTTPacket_connectData* options) 00028 { 00029 int len = 0; 00030 00031 FUNC_ENTRY; 00032 00033 if (options->MQTTVersion == 3) 00034 len = 12; /* variable depending on MQTT or MQIsdp */ 00035 else if (options->MQTTVersion == 4) 00036 len = 10; 00037 00038 len += MQTTstrlen(options->clientID)+2; 00039 if (options->willFlag) 00040 len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2; 00041 if (options->username.cstring || options->username.lenstring.data) 00042 len += MQTTstrlen(options->username)+2; 00043 if (options->password.cstring || options->password.lenstring.data) 00044 len += MQTTstrlen(options->password)+2; 00045 00046 FUNC_EXIT_RC(len); 00047 return len; 00048 } 00049 00050 00051 /** 00052 * Serializes the connect options into the buffer. 00053 * @param buf the buffer into which the packet will be serialized 00054 * @param len the length in bytes of the supplied buffer 00055 * @param options the options to be used to build the connect packet 00056 * @return serialized length, or error if 0 00057 */ 00058 int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options) 00059 { 00060 unsigned char *ptr = buf; 00061 MQTTHeader header = {0}; 00062 MQTTConnectFlags flags = {0}; 00063 int len = 0; 00064 int rc = -1; 00065 00066 FUNC_ENTRY; 00067 if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen) 00068 { 00069 rc = MQTTPACKET_BUFFER_TOO_SHORT; 00070 goto exit; 00071 } 00072 00073 header.byte = 0; 00074 header.bits.type = CONNECT; 00075 writeChar(&ptr, header.byte); /* write header */ 00076 00077 ptr += MQTTPacket_encode(ptr, len); /* write remaining length */ 00078 00079 if (options->MQTTVersion == 4) 00080 { 00081 writeCString(&ptr, "MQTT"); 00082 writeChar(&ptr, (char) 4); 00083 } 00084 else 00085 { 00086 writeCString(&ptr, "MQIsdp"); 00087 writeChar(&ptr, (char) 3); 00088 } 00089 00090 flags.all = 0; 00091 flags.bits.cleansession = options->cleansession; 00092 flags.bits.will = (options->willFlag) ? 1 : 0; 00093 if (flags.bits.will) 00094 { 00095 flags.bits.willQoS = options->will.qos; 00096 flags.bits.willRetain = options->will.retained; 00097 } 00098 00099 if (options->username.cstring || options->username.lenstring.data) 00100 flags.bits.username = 1; 00101 if (options->password.cstring || options->password.lenstring.data) 00102 flags.bits.password = 1; 00103 00104 writeChar(&ptr, flags.all); 00105 writeInt(&ptr, options->keepAliveInterval); 00106 writeMQTTString(&ptr, options->clientID); 00107 if (options->willFlag) 00108 { 00109 writeMQTTString(&ptr, options->will.topicName); 00110 writeMQTTString(&ptr, options->will.message); 00111 } 00112 if (flags.bits.username) 00113 writeMQTTString(&ptr, options->username); 00114 if (flags.bits.password) 00115 writeMQTTString(&ptr, options->password); 00116 00117 rc = ptr - buf; 00118 00119 exit: FUNC_EXIT_RC(rc); 00120 return rc; 00121 } 00122 00123 00124 /** 00125 * Deserializes the supplied (wire) buffer into connack data - return code 00126 * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) 00127 * @param connack_rc returned integer value of the connack return code 00128 * @param buf the raw buffer data, of the correct length determined by the remaining length field 00129 * @param len the length in bytes of the data in the supplied buffer 00130 * @return error code. 1 is success, 0 is failure 00131 */ 00132 int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen) 00133 { 00134 MQTTHeader header = {0}; 00135 unsigned char* curdata = buf; 00136 unsigned char* enddata = NULL; 00137 int rc = 0; 00138 int mylen; 00139 MQTTConnackFlags flags = {0}; 00140 00141 FUNC_ENTRY; 00142 header.byte = readChar(&curdata); 00143 if (header.bits.type != CONNACK) 00144 goto exit; 00145 00146 curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 00147 enddata = curdata + mylen; 00148 if (enddata - curdata < 2) 00149 goto exit; 00150 00151 flags.all = readChar(&curdata); 00152 *sessionPresent = flags.bits.sessionpresent; 00153 *connack_rc = readChar(&curdata); 00154 00155 rc = 1; 00156 exit: 00157 FUNC_EXIT_RC(rc); 00158 return rc; 00159 } 00160 00161 00162 00163 /** 00164 * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket 00165 * @param buf the buffer into which the packet will be serialized 00166 * @param buflen the length in bytes of the supplied buffer, to avoid overruns 00167 * @param packettype the message type 00168 * @return serialized length, or error if 0 00169 */ 00170 int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype) 00171 { 00172 MQTTHeader header = {0}; 00173 int rc = -1; 00174 unsigned char *ptr = buf; 00175 00176 FUNC_ENTRY; 00177 if (buflen < 2) 00178 { 00179 rc = MQTTPACKET_BUFFER_TOO_SHORT; 00180 goto exit; 00181 } 00182 header.byte = 0; 00183 header.bits.type = packettype; 00184 writeChar(&ptr, header.byte); /* write header */ 00185 00186 ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */ 00187 rc = ptr - buf; 00188 exit: 00189 FUNC_EXIT_RC(rc); 00190 return rc; 00191 } 00192 00193 00194 /** 00195 * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 00196 * @param buf the buffer into which the packet will be serialized 00197 * @param buflen the length in bytes of the supplied buffer, to avoid overruns 00198 * @return serialized length, or error if 0 00199 */ 00200 int MQTTSerialize_disconnect(unsigned char* buf, int buflen) 00201 { 00202 return MQTTSerialize_zero(buf, buflen, DISCONNECT); 00203 } 00204 00205 00206 /** 00207 * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 00208 * @param buf the buffer into which the packet will be serialized 00209 * @param buflen the length in bytes of the supplied buffer, to avoid overruns 00210 * @return serialized length, or error if 0 00211 */ 00212 int MQTTSerialize_pingreq(unsigned char* buf, int buflen) 00213 { 00214 return MQTTSerialize_zero(buf, buflen, PINGREQ); 00215 }
Generated on Tue Jul 12 2022 17:50:32 by 1.7.2