1 /*******************************************************************************
2  * Copyright (c) 2014 IBM Corp.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  *    http://www.eclipse.org/legal/epl-v10.html
10  * and the Eclipse Distribution License is available at
11  *   http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  *    Ian Craggs - initial API and implementation and/or initial documentation
15  *******************************************************************************/
16 
17 #include "StackTrace.h"
18 #include "MQTTPacket.h"
19 
20 #include <string.h>
21 
22 
23 const char* MQTTPacket_names[] =
24 {
25 	"RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
26 	"PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK",
27 	"PINGREQ", "PINGRESP", "DISCONNECT"
28 };
29 
30 
MQTTPacket_getName(unsigned short packetid)31 const char* MQTTPacket_getName(unsigned short packetid)
32 {
33 	return MQTTPacket_names[packetid];
34 }
35 
36 
MQTTStringFormat_connect(char * strbuf,int strbuflen,MQTTPacket_connectData * data)37 int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data)
38 {
39 	int strindex = 0;
40 
41 	strindex = snprintf(strbuf, strbuflen,
42 			"CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %d",
43 			(int)data->MQTTVersion, data->clientID.lenstring.len, data->clientID.lenstring.data,
44 			(int)data->cleansession, data->keepAliveInterval);
45 	if (data->willFlag)
46 		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
47 				", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
48 				data->will.qos, data->will.retained,
49 				data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
50 				data->will.message.lenstring.len, data->will.message.lenstring.data);
51 	if (data->username.lenstring.data && data->username.lenstring.len > 0)
52 		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
53 				", user name %.*s", data->username.lenstring.len, data->username.lenstring.data);
54 	if (data->password.lenstring.data && data->password.lenstring.len > 0)
55 		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
56 				", password %.*s", data->password.lenstring.len, data->password.lenstring.data);
57 	return strindex;
58 }
59 
60 
MQTTStringFormat_connack(char * strbuf,int strbuflen,unsigned char connack_rc,unsigned char sessionPresent)61 int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent)
62 {
63 	int strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
64 	return strindex;
65 }
66 
67 
MQTTStringFormat_publish(char * strbuf,int strbuflen,unsigned char dup,int qos,unsigned char retained,unsigned short packetid,MQTTString topicName,unsigned char * payload,int payloadlen)68 int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
69 		unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen)
70 {
71 	int strindex = snprintf(strbuf, strbuflen,
72 				"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
73 				dup, qos, retained, packetid,
74 				(topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
75 				payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
76 	return strindex;
77 }
78 
79 
MQTTStringFormat_ack(char * strbuf,int strbuflen,unsigned char packettype,unsigned char dup,unsigned short packetid)80 int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
81 {
82 	int strindex = snprintf(strbuf, strbuflen, "%s, packet id %d", MQTTPacket_names[packettype], packetid);
83 	if (dup)
84 		strindex += snprintf(strbuf + strindex, strbuflen - strindex, ", dup %d", dup);
85 	return strindex;
86 }
87 
88 
MQTTStringFormat_subscribe(char * strbuf,int strbuflen,unsigned char dup,unsigned short packetid,int count,MQTTString topicFilters[],int requestedQoSs[])89 int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
90 		MQTTString topicFilters[], int requestedQoSs[])
91 {
92 	return snprintf(strbuf, strbuflen,
93 		"SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
94 		dup, packetid, count,
95 		topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
96 		requestedQoSs[0]);
97 }
98 
99 
MQTTStringFormat_suback(char * strbuf,int strbuflen,unsigned short packetid,int count,int * grantedQoSs)100 int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs)
101 {
102 	return snprintf(strbuf, strbuflen,
103 		"SUBACK packet id %d count %d granted qos %d", packetid, count, grantedQoSs[0]);
104 }
105 
106 
MQTTStringFormat_unsubscribe(char * strbuf,int strbuflen,unsigned char dup,unsigned short packetid,int count,MQTTString topicFilters[])107 int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
108 		int count, MQTTString topicFilters[])
109 {
110 	return snprintf(strbuf, strbuflen,
111 					"UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
112 					dup, packetid, count,
113 					topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
114 }
115 
116 
117 #if defined(MQTT_CLIENT)
MQTTFormat_toClientString(char * strbuf,int strbuflen,unsigned char * buf,int buflen)118 char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
119 {
120 	int index = 0;
121 	int rem_length = 0;
122 	MQTTHeader header = {0};
123 	int strindex = 0;
124 
125 	header.byte = buf[index++];
126 	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
127 
128 	switch (header.bits.type)
129 	{
130 
131 	case CONNACK:
132 	{
133 		unsigned char sessionPresent, connack_rc;
134 		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
135 			strindex = MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
136 	}
137 	break;
138 	case PUBLISH:
139 	{
140 		unsigned char dup, retained, *payload;
141 		unsigned short packetid;
142 		int qos, payloadlen;
143 		MQTTString topicName = MQTTString_initializer;
144 		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
145 				&payload, &payloadlen, buf, buflen) == 1)
146 			strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
147 					topicName, payload, payloadlen);
148 	}
149 	break;
150 	case PUBACK:
151 	case PUBREC:
152 	case PUBREL:
153 	case PUBCOMP:
154 	{
155 		unsigned char packettype, dup;
156 		unsigned short packetid;
157 		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
158 			strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
159 	}
160 	break;
161 	case SUBACK:
162 	{
163 		unsigned short packetid;
164 		int maxcount = 1, count = 0;
165 		int grantedQoSs[1];
166 		if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
167 			strindex = MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
168 	}
169 	break;
170 	case UNSUBACK:
171 	{
172 		unsigned short packetid;
173 		if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
174 			strindex = MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
175 	}
176 	break;
177 	case PINGREQ:
178 	case PINGRESP:
179 	case DISCONNECT:
180 		strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
181 		break;
182 	}
183 	return strbuf;
184 }
185 #endif
186 
187 #if defined(MQTT_SERVER)
MQTTFormat_toServerString(char * strbuf,int strbuflen,unsigned char * buf,int buflen)188 char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
189 {
190 	int index = 0;
191 	int rem_length = 0;
192 	MQTTHeader header = {0};
193 	int strindex = 0;
194 
195 	header.byte = buf[index++];
196 	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
197 
198 	switch (header.bits.type)
199 	{
200 	case CONNECT:
201 	{
202 		MQTTPacket_connectData data;
203 		int rc;
204 		if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1)
205 			strindex = MQTTStringFormat_connect(strbuf, strbuflen, &data);
206 	}
207 	break;
208 	case PUBLISH:
209 	{
210 		unsigned char dup, retained, *payload;
211 		unsigned short packetid;
212 		int qos, payloadlen;
213 		MQTTString topicName = MQTTString_initializer;
214 		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
215 				&payload, &payloadlen, buf, buflen) == 1)
216 			strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
217 					topicName, payload, payloadlen);
218 	}
219 	break;
220 	case PUBACK:
221 	case PUBREC:
222 	case PUBREL:
223 	case PUBCOMP:
224 	{
225 		unsigned char packettype, dup;
226 		unsigned short packetid;
227 		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
228 			strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
229 	}
230 	break;
231 	case SUBSCRIBE:
232 	{
233 		unsigned char dup;
234 		unsigned short packetid;
235 		int maxcount = 1, count = 0;
236 		MQTTString topicFilters[1];
237 		int requestedQoSs[1];
238 		if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
239 				topicFilters, requestedQoSs, buf, buflen) == 1)
240 			strindex = MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);;
241 	}
242 	break;
243 	case UNSUBSCRIBE:
244 	{
245 		unsigned char dup;
246 		unsigned short packetid;
247 		int maxcount = 1, count = 0;
248 		MQTTString topicFilters[1];
249 		if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
250 			strindex =  MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
251 	}
252 	break;
253 	case PINGREQ:
254 	case PINGRESP:
255 	case DISCONNECT:
256 		strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
257 		break;
258 	}
259 	strbuf[strbuflen] = '\0';
260 	return strbuf;
261 }
262 #endif
263