mirror of
https://github.com/eclipse/paho.mqtt-sn.embedded-c.git
synced 2025-12-13 07:26:52 +01:00
Latest updates - qos1 publish sample
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
gcc -Wall qos0pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub -Os -s
|
||||
gcc -Wall qos-1pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub -Os -s
|
||||
gcc -Wall qos1pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos1pub -Os -s
|
||||
|
||||
195
samples/qos1pub.c
Normal file
195
samples/qos1pub.c
Normal file
@@ -0,0 +1,195 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(SOCKET_ERROR)
|
||||
/** error in socket operation */
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
/* default on Windows is 64 - increase to make Linux and Windows the same */
|
||||
#define FD_SETSIZE 1024
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#define EAGAIN WSAEWOULDBLOCK
|
||||
#define EINTR WSAEINTR
|
||||
#define EINVAL WSAEINVAL
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define ENOTCONN WSAENOTCONN
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define ioctl ioctlsocket
|
||||
#define socklen_t int
|
||||
#else
|
||||
#define INVALID_SOCKET SOCKET_ERROR
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <Iphlpapi.h>
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
|
||||
int Socket_error(char* aString, int sock)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
int errno;
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
errno = WSAGetLastError();
|
||||
#endif
|
||||
if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK)
|
||||
{
|
||||
if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET))
|
||||
{
|
||||
int orig_errno = errno;
|
||||
char* errmsg = strerror(errno);
|
||||
|
||||
printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock);
|
||||
}
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
int sendPacketBuffer(int asocket, char* host, int port, unsigned char* buf, int buflen)
|
||||
{
|
||||
struct sockaddr_in cliaddr;
|
||||
int rc = 0;
|
||||
|
||||
memset(&cliaddr, 0, sizeof(cliaddr));
|
||||
cliaddr.sin_family = AF_INET;
|
||||
cliaddr.sin_addr.s_addr = inet_addr(host);
|
||||
cliaddr.sin_port = htons(port);
|
||||
|
||||
if ((rc = sendto(asocket, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR)
|
||||
Socket_error("sendto", asocket);
|
||||
else
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int mysock = 0;
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1884;
|
||||
|
||||
int getdata(unsigned char* buf, size_t count)
|
||||
{
|
||||
int rc = recvfrom(mysock, buf, count, 0, NULL, NULL);
|
||||
//printf("received %d bytes count %d\n", rc, (int)count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[200];
|
||||
int buflen = sizeof(buf);
|
||||
MQTTSN_topicid topic;
|
||||
unsigned char* payload = (unsigned char*)"mypayload";
|
||||
int payloadlen = strlen((char*)payload);
|
||||
int len = 0;
|
||||
int dup = 0;
|
||||
int qos = 1;
|
||||
int retained = 0, packetid = 1;
|
||||
char *topicname = "a long topic name";
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
mysock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (mysock == INVALID_SOCKET)
|
||||
rc = Socket_error("socket", mysock);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = sendPacketBuffer(mysock, host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_CONNACK)
|
||||
{
|
||||
int connack_rc = -1;
|
||||
|
||||
if (MQTTSNDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0)
|
||||
{
|
||||
printf("Unable to connect, return code %d\n", connack_rc);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("connected rc %d\n", connack_rc);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
/* publish with short name */
|
||||
topic.type = MQTTSN_TOPIC_TYPE_SHORT;
|
||||
memcpy(topic.data.name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen - len, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = sendPacketBuffer(mysock, host, port, buf, len);
|
||||
|
||||
/* wait for puback */
|
||||
if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_PUBACK)
|
||||
{
|
||||
unsigned short packet_id, topic_id;
|
||||
unsigned char returncode;
|
||||
|
||||
if (MQTTSNDeserialize_puback(&topic_id, &packet_id, &returncode, buf, buflen) != 1 || returncode != MQTTSN_RC_ACCEPTED)
|
||||
printf("Unable to publish, return code %d\n", returncode);
|
||||
else
|
||||
printf("puback received, id %d\n", packet_id);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
len = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
rc = sendPacketBuffer(mysock, host, port, buf, len);
|
||||
|
||||
exit:
|
||||
rc = shutdown(mysock, SHUT_WR);
|
||||
rc = close(mysock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -39,5 +39,18 @@ int MQTTSNSerialize_connack(unsigned char* buf, int buflen, int connack_rc);
|
||||
int MQTTSNDeserialize_connack(int* connack_rc, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_disconnect(unsigned char* buf, int buflen, int duration);
|
||||
int MQTTSNDeserialize_disconnect(int* duration, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_pingreq(unsigned char* buf, int buflen, MQTTString clientid);
|
||||
int MQTTSNDeserialize_pingreq(MQTTString* clientID, unsigned char* buf, int len);
|
||||
|
||||
int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNCONNECT_H_ */
|
||||
|
||||
@@ -88,15 +88,15 @@ int MQTTSNDeserialize_connack(int* connack_rc, unsigned char* buf, int buflen)
|
||||
int mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decodeBuf(curdata, &mylen)); /* read length */
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 2)
|
||||
if (enddata - buf < 3)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_CONNACK)
|
||||
goto exit;
|
||||
|
||||
*connack_rc = readInt(&curdata);
|
||||
*connack_rc = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
@@ -151,3 +151,208 @@ exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer, to avoid overruns
|
||||
* @param clientid optional string, not added to packet string == NULL
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_pingreq(unsigned char* buf, int buflen, MQTTString clientid)
|
||||
{
|
||||
int rc = -1;
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTstrlen(clientid) + 1)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_PINGREQ); /* write message type */
|
||||
|
||||
writeMQTTSNString(&ptr, clientid);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_PINGRESP)
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willtopicupd packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param len the length in bytes of the supplied buffer
|
||||
* @param willQoS the qos of the will message
|
||||
* @param willRetain the retained flag of the will message
|
||||
* @param willTopic the topic of the will message
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willtopicupd(unsigned char* buf, int buflen, int willQoS, int willRetain, MQTTString willTopic)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTstrlen(willTopic) + 2)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLTOPICUPD); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.QoS = willQoS;
|
||||
flags.bits.retain = willRetain;
|
||||
writeChar(&ptr, flags.all);
|
||||
|
||||
writeMQTTSNString(&ptr, willTopic);
|
||||
|
||||
rc = ptr - buf;
|
||||
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willmsgupd packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param len the length in bytes of the supplied buffersage
|
||||
* @param willMsg the will message
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willmsgupd(unsigned char* buf, int buflen, MQTTString willMsg)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTstrlen(willMsg) + 1)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLMSGUPD); /* write message type */
|
||||
|
||||
writeMQTTSNString(&ptr, willMsg);
|
||||
|
||||
rc = ptr - buf;
|
||||
|
||||
exit: FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = -1;
|
||||
int mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (MQTTSNPacket_decode(curdata++, buflen, &mylen) != 1) /* read length */
|
||||
goto exit;
|
||||
if (mylen > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 1)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_WILLTOPICREQ)
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = -1;
|
||||
int mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (MQTTSNPacket_decode(curdata++, buflen, &mylen) != 1) /* read length */
|
||||
goto exit;
|
||||
if (mylen > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 1)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_WILLMSGREQ)
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ int MQTTSNDeserialize_connect(MQTTSNPacket_connectData* data, unsigned char* buf
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decodeBuf(curdata, &mylen)); /* read length */
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
@@ -94,3 +94,155 @@ exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into disconnect data - optional duration
|
||||
* @param duration returned integer value of the duration field, -1 if no duration was specified
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_disconnect(int* duration, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = -1;
|
||||
int mylen;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 1)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_DISCONNECT)
|
||||
goto exit;
|
||||
|
||||
if (enddata - curdata == 2)
|
||||
*duration = readInt(&curdata);
|
||||
else if (enddata != curdata)
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willtopicreq packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLTOPICREQ);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willmsgreq packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLMSGREQ);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into pingreq data
|
||||
* @param clientID the connect data structure to be filled out
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param len the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_pingreq(MQTTString* clientID, unsigned char* buf, int len)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = &buf[len];
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 1)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_PINGREQ)
|
||||
goto exit;
|
||||
|
||||
if (!readMQTTSNString(clientID, &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a pingresp packet into the supplied buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 2)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 2); /* write length */
|
||||
writeChar(&ptr, MQTTSN_PINGRESP);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ int MQTTSNDeserialize_publish(int* dup, int* qos, int* retained, unsigned short*
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decodeBuf(curdata, &mylen)); /* read length */
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
@@ -95,7 +95,7 @@ int MQTTSNDeserialize_puback(unsigned short* topicid, unsigned short* packetid,
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decodeBuf(curdata, &mylen)); /* read length */
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
@@ -130,7 +130,7 @@ int MQTTSNDeserialize_ack(unsigned char* type, unsigned short* packetid, unsigne
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decodeBuf(curdata, &mylen)); /* read length */
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
@@ -83,32 +83,26 @@ int MQTTSNPacket_encode(unsigned char* buf, int length)
|
||||
* @param value the decoded length returned
|
||||
* @return the number of bytes read from the socket
|
||||
*/
|
||||
int MQTTSNPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
|
||||
int MQTTSNPacket_decode(unsigned char* buf, size_t buflen, int* value)
|
||||
{
|
||||
unsigned char c;
|
||||
int rc = MQTTSNPACKET_READ_ERROR;
|
||||
int len = MQTTSNPACKET_READ_ERROR;
|
||||
#define MAX_NO_OF_LENGTH_BYTES 3
|
||||
|
||||
FUNC_ENTRY;
|
||||
rc = (*getcharfn)(&c, 1);
|
||||
if (rc != 1)
|
||||
if (buflen <= 0)
|
||||
goto exit;
|
||||
|
||||
if (c == 1)
|
||||
if (buf[0] == 1)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
unsigned char* ptr = buf;
|
||||
|
||||
rc = (*getcharfn)(buf, 2);
|
||||
if (rc != 2)
|
||||
unsigned char* bufptr = &buf[1];
|
||||
if (buflen < 3)
|
||||
goto exit;
|
||||
*value = readInt(&ptr);
|
||||
*value = readInt(&bufptr);
|
||||
len = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = c;
|
||||
*value = buf[0];
|
||||
len = 1;
|
||||
}
|
||||
exit:
|
||||
@@ -117,25 +111,6 @@ exit:
|
||||
}
|
||||
|
||||
|
||||
static unsigned char* bufptr;
|
||||
|
||||
int bufchar(unsigned char* c, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
*c = *bufptr++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int MQTTSNPacket_decodeBuf(unsigned char* buf, int* value)
|
||||
{
|
||||
bufptr = buf;
|
||||
return MQTTSNPacket_decode(bufchar, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates an integer from two bytes read from the input buffer
|
||||
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
|
||||
@@ -233,8 +208,14 @@ int readMQTTSNString(MQTTString* mqttstring, unsigned char** pptr, unsigned char
|
||||
|
||||
FUNC_ENTRY;
|
||||
mqttstring->lenstring.len = enddata - *pptr;
|
||||
mqttstring->lenstring.data = (char*)*pptr;
|
||||
*pptr += mqttstring->lenstring.len;
|
||||
if (mqttstring->lenstring.len > 0)
|
||||
{
|
||||
mqttstring->lenstring.data = (char*)*pptr;
|
||||
*pptr += mqttstring->lenstring.len;
|
||||
}
|
||||
else
|
||||
mqttstring->lenstring.data = NULL;
|
||||
mqttstring->cstring = NULL;
|
||||
rc = 1;
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
@@ -265,24 +246,23 @@ int MQTTstrlen(MQTTString mqttstring)
|
||||
* @param getfn pointer to a function which will read any number of bytes from the needed source
|
||||
* @return integer MQTT packet type, or MQTTSNPACKET_READ_ERROR on error
|
||||
*/
|
||||
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
|
||||
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, size_t))
|
||||
{
|
||||
int rc = MQTTSNPACKET_READ_ERROR;
|
||||
const int MQTTSN_MIN_PACKET_LENGTH = 3;
|
||||
int len = 0; /* the length of the whole packet including length field */
|
||||
int lenlen = 0; /* the length of the length field: 1 or 3 */
|
||||
int lenlen = 0;
|
||||
int datalen = 0;
|
||||
|
||||
/* 1. read the length. This is variable in itself */
|
||||
lenlen = MQTTSNPacket_decode(getfn, &len);
|
||||
if (lenlen <= 0)
|
||||
/* 1. read a packet - UDP style */
|
||||
if ((len = (*getfn)(buf, buflen)) < MQTTSN_MIN_PACKET_LENGTH)
|
||||
goto exit;
|
||||
|
||||
/* 2. read the length. This is variable in itself */
|
||||
lenlen = MQTTSNPacket_decode(buf, len, &datalen);
|
||||
if (datalen != len)
|
||||
goto exit; /* there was an error */
|
||||
|
||||
if (MQTTSNPacket_encode(buf, len) != lenlen) /* put the original remaining length back into the buffer */
|
||||
goto exit;
|
||||
|
||||
/* 2. read the rest of the data using a callback */
|
||||
if ((*getfn)(buf + lenlen, len - lenlen) != len - lenlen)
|
||||
goto exit;
|
||||
|
||||
rc = buf[lenlen]; /* return the packet type */
|
||||
exit:
|
||||
return rc;
|
||||
|
||||
@@ -126,12 +126,13 @@ int MQTTstrlen(MQTTString mqttstring);
|
||||
#include "MQTTSNUnsubscribe.h"
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char* MQTTSNPacket_name(int ptype);
|
||||
int MQTTSNPacket_len(int length);
|
||||
|
||||
int MQTTSNPacket_encode(unsigned char* buf, int length);
|
||||
int MQTTSNPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
|
||||
int MQTTSNPacket_decodeBuf(unsigned char* buf, int* value);
|
||||
int MQTTSNPacket_decode(unsigned char* buf, size_t buflen, int* value);
|
||||
|
||||
int readInt(unsigned char** pptr);
|
||||
char readChar(unsigned char** pptr);
|
||||
@@ -143,6 +144,8 @@ void writeMQTTSNString(unsigned char** pptr, MQTTString mqttstring);
|
||||
|
||||
int MQTTDeserialize_ack(int* type, int* dup, int* packetid, char* buf, int buflen);
|
||||
|
||||
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, size_t));
|
||||
|
||||
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
28
src/MQTTSNSubscribeClient.c
Normal file
28
src/MQTTSNSubscribeClient.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014 IBM Corp.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Ian Craggs - initial API and implementation and/or initial documentation
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
|
||||
int MQTTDeserialize_subscribe(int* dup, int* packetid, int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[],
|
||||
char* buf, int buflen)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int MQTTSerialize_suback(char* buf, int buflen, int packetid, int count, int* grantedQoSs)
|
||||
{
|
||||
|
||||
92
test/test1.c
92
test/test1.c
@@ -303,6 +303,8 @@ int test1(struct Options options)
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
MQTTString clientid = MQTTString_initializer, clientid_after = MQTTString_initializer;
|
||||
int duration_after = -1;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
@@ -326,6 +328,63 @@ int test1(struct Options options)
|
||||
rc = checkConnectPackets(&data, &data_after);
|
||||
assert("packets should be the same", rc == 1, "packets were different\n", rc);
|
||||
|
||||
/* Pingreq without clientid */
|
||||
rc = MQTTSNSerialize_pingreq(buf, buflen, clientid);
|
||||
assert("good rc from serialize pingreq", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_pingreq(&clientid_after, buf, buflen);
|
||||
assert("good rc from deserialize pingreq", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("ClientIDs should be the same",
|
||||
checkMQTTStrings(clientid, clientid_after), "ClientIDs were different\n", rc);
|
||||
|
||||
/* Pingreq with clientid */
|
||||
clientid.cstring = "this is me";
|
||||
rc = MQTTSNSerialize_pingreq(buf, buflen, clientid);
|
||||
assert("good rc from serialize pingreq", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_pingreq(&clientid_after, buf, buflen);
|
||||
assert("good rc from deserialize pingreq", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("ClientIDs should be the same",
|
||||
checkMQTTStrings(clientid, clientid_after), "ClientIDs were different\n", rc);
|
||||
|
||||
rc = MQTTSNSerialize_pingresp(buf, buflen);
|
||||
assert("good rc from serialize pingresp", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_pingresp(buf, buflen);
|
||||
assert("good rc from deserialize pingresp", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* Disconnect without duration */
|
||||
rc = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
assert("good rc from serialize disconnect", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_disconnect(&duration_after, buf, buflen);
|
||||
assert("good rc from deserialize disconnect", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("durations should be the same", 0 == duration_after, "durations were different\n", rc);
|
||||
|
||||
/* Disconnect with duration */
|
||||
rc = MQTTSNSerialize_disconnect(buf, buflen, 33);
|
||||
assert("good rc from serialize disconnect", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_disconnect(&duration_after, buf, buflen);
|
||||
assert("good rc from deserialize disconnect", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("durations should be the same", 33 == duration_after, "durations were different\n", rc);
|
||||
|
||||
/* Pingreq with clientid */
|
||||
clientid.cstring = "this is me";
|
||||
rc = MQTTSNSerialize_pingreq(buf, buflen, clientid);
|
||||
assert("good rc from serialize pingreq", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_pingreq(&clientid_after, buf, buflen);
|
||||
assert("good rc from deserialize pingreq", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
@@ -415,6 +474,37 @@ int test2(struct Options options)
|
||||
}
|
||||
|
||||
|
||||
int test3(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test3\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 3 - will messages");
|
||||
|
||||
rc = MQTTSNSerialize_willtopicreq(buf, buflen);
|
||||
assert("good rc from serialize willtopicreq", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willtopicreq(buf, buflen);
|
||||
assert("good rc from deserialize willtopicreq", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNSerialize_willmsgreq(buf, buflen);
|
||||
assert("good rc from serialize willmsgreq", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willmsgreq(buf, rc);
|
||||
assert("good rc from deserialize willmsgreq", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int test3(struct Options options)
|
||||
{
|
||||
@@ -599,7 +689,7 @@ int test6(struct Options options)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int (*tests[])() = {NULL, test1, test2, /*test3, test4, test5,*/ test6};
|
||||
int (*tests[])() = {NULL, test1, test2, test3, /*test4, test5,*/ test6};
|
||||
|
||||
xml = fopen("TEST-test1.xml", "w");
|
||||
fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
|
||||
|
||||
Reference in New Issue
Block a user