mirror of
https://github.com/eclipse/paho.mqtt-sn.embedded-c.git
synced 2025-12-13 07:26:52 +01:00
Move MQTTSNPacket into subdirectory
This commit is contained in:
193
MQTTSNPacket/samples/IBMIoTUDPExample.cpp
Normal file
193
MQTTSNPacket/samples/IBMIoTUDPExample.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
/*******************************************************************************
|
||||
* 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 - refactoring to remove STL and other changes
|
||||
*******************************************************************************/
|
||||
|
||||
#define WARN printf
|
||||
|
||||
#include "MQTTClient.h"
|
||||
|
||||
#define DEFAULT_STACK_SIZE -1
|
||||
|
||||
#include "linux.cpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// Configuration values needed to connect to IBM IoT Cloud
|
||||
#define ORG "quickstart" // For a registered connection, replace with your org
|
||||
#define ID "8002f7f1ad23" // For a registered connection, replace with your id
|
||||
#define AUTH_TOKEN "" // For a registered connection, replace with your auth-token
|
||||
#define TYPE "mytype" // For a registered connection, replace with your type
|
||||
|
||||
#define MQTT_PORT 1883
|
||||
#define MQTT_TLS_PORT 8883
|
||||
#define IBM_IOT_PORT MQTT_PORT
|
||||
|
||||
#define MQTT_MAX_PACKET_SIZE 250
|
||||
|
||||
bool quickstartMode = true;
|
||||
char org[11] = ORG;
|
||||
char type[30] = TYPE;
|
||||
char id[30] = ID; // mac without colons
|
||||
char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
|
||||
|
||||
bool connected = false;
|
||||
const char* joystickPos = "CENTRE";
|
||||
int blink_interval = 0;
|
||||
|
||||
|
||||
|
||||
int connect(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
|
||||
{
|
||||
const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com";
|
||||
|
||||
char hostname[strlen(org) + strlen(iot_ibm) + 1];
|
||||
sprintf(hostname, "%s%s", org, iot_ibm);
|
||||
DEBUG("connecting to %s\n", hostname);
|
||||
int rc = ipstack->connect(hostname, IBM_IOT_PORT);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
// Construct clientId - d:org:type:id
|
||||
char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
|
||||
sprintf(clientId, "d:%s:%s:%s", org, type, id);
|
||||
DEBUG("clientid is %s\n", clientId);
|
||||
|
||||
// MQTT Connect
|
||||
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
|
||||
data.MQTTVersion = 4;
|
||||
data.clientID.cstring = clientId;
|
||||
|
||||
if (!quickstartMode)
|
||||
{
|
||||
data.username.cstring = "use-token-auth";
|
||||
data.password.cstring = auth_token;
|
||||
}
|
||||
|
||||
if ((rc = client->connect(data)) == 0)
|
||||
connected = true;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int getConnTimeout(int attemptNumber)
|
||||
{ // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
|
||||
// after 20 attempts, retry every 10 minutes
|
||||
return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
|
||||
}
|
||||
|
||||
|
||||
void attemptConnect(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
|
||||
{
|
||||
int retryAttempt = 0;
|
||||
connected = false;
|
||||
|
||||
while (connect(client, ipstack) != 0)
|
||||
{
|
||||
int timeout = getConnTimeout(++retryAttempt);
|
||||
WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
|
||||
|
||||
// if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
|
||||
// or maybe just add the proper members to do this disconnect and call attemptConnect(...)
|
||||
|
||||
sleep(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int publish(MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE>* client, IPStack* ipstack)
|
||||
{
|
||||
MQTT::Message message;
|
||||
char* pubTopic = "iot-2/evt/status/fmt/json";
|
||||
static const char* joypos[] = {"LEFT", "RIGHT", "CENTRE", "UP", "DOWN"};
|
||||
|
||||
char buf[250];
|
||||
sprintf(buf,
|
||||
"{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}",
|
||||
(rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) + 18.0, joypos[rand() % 5], (rand() % 10) * 30.0, (rand() % 10) * 30.0);
|
||||
//MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read());
|
||||
message.qos = MQTT::QOS0;
|
||||
message.retained = false;
|
||||
message.dup = false;
|
||||
message.payload = (void*)buf;
|
||||
message.payloadlen = strlen(buf);
|
||||
|
||||
LOG("Publishing %s\n", buf);
|
||||
return client->publish(pubTopic, message);
|
||||
}
|
||||
|
||||
|
||||
void messageArrived(MQTT::MessageData& md)
|
||||
{
|
||||
MQTT::Message &message = md.message;
|
||||
char topic[md.topicName.lenstring.len + 1];
|
||||
|
||||
sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);
|
||||
|
||||
LOG("Message arrived on topic %s: %.*s\n", topic, message.payloadlen, message.payload);
|
||||
|
||||
// Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
|
||||
char* start = strstr(topic, "/cmd/") + 5;
|
||||
int len = strstr(topic, "/fmt/") - start;
|
||||
|
||||
if (memcmp(start, "blink", len) == 0)
|
||||
{
|
||||
char payload[message.payloadlen + 1];
|
||||
sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);
|
||||
|
||||
char* pos = strchr(payload, '}');
|
||||
if (pos != NULL)
|
||||
{
|
||||
*pos = '\0';
|
||||
if ((pos = strchr(payload, ':')) != NULL)
|
||||
{
|
||||
int blink_rate = atoi(pos + 1);
|
||||
blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
WARN("Unsupported command: %.*s\n", len, start);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
quickstartMode = (strcmp(org, "quickstart") == 0);
|
||||
|
||||
IPStack ipstack = IPStack();
|
||||
MQTT::Client<IPStack, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
|
||||
|
||||
attemptConnect(&client, &ipstack);
|
||||
|
||||
if (!quickstartMode)
|
||||
{
|
||||
int rc = 0;
|
||||
if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0)
|
||||
WARN("rc from MQTT subscribe is %d\n", rc);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while (true)
|
||||
{
|
||||
if (++count == 100)
|
||||
{ // Publish a message every second
|
||||
if (publish(&client, &ipstack) != 0)
|
||||
attemptConnect(&client, &ipstack); // if we have lost the connection
|
||||
count = 0;
|
||||
}
|
||||
client.yield(10); // allow the MQTT client to receive messages
|
||||
}
|
||||
}
|
||||
|
||||
7
MQTTSNPacket/samples/build
Executable file
7
MQTTSNPacket/samples/build
Executable file
@@ -0,0 +1,7 @@
|
||||
gcc -Wall -c transport.c -Os -s
|
||||
gcc -Wall qos0pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub -Os -s
|
||||
gcc -Wall qos0pub_register.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub_register -Os -s
|
||||
gcc -Wall qos-1pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub -Os -s
|
||||
gcc -Wall qos-1pub_extended.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub_extended -Os -s
|
||||
gcc -Wall qos1pub.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos1pub -Os -s
|
||||
gcc -Wall pub0sub1.c transport.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c ../src/MQTTSNSubscribeClient.c -o pub0sub1 -Os -s
|
||||
7
MQTTSNPacket/samples/linux/udp/build
Normal file
7
MQTTSNPacket/samples/linux/udp/build
Normal file
@@ -0,0 +1,7 @@
|
||||
gcc -Wall -c lowlevel.c -Os -s
|
||||
gcc -Wall qos0pub.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub -Os -s
|
||||
gcc -Wall qos0pub_register.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub_register -Os -s
|
||||
gcc -Wall qos-1pub.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub -Os -s
|
||||
gcc -Wall qos-1pub_extended.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub_extended -Os -s
|
||||
gcc -Wall qos1pub.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos1pub -Os -s
|
||||
gcc -Wall pub0sub1.c lowlevel.o -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c ../src/MQTTSNSubscribeClient.c -o pub0sub1 -Os -s
|
||||
141
MQTTSNPacket/samples/linux/udp/lowlevel.c
Normal file
141
MQTTSNPacket/samples/linux/udp/lowlevel.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension
|
||||
*******************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
This simple low-level implementation assumes a single connection for a single thread. Thus, a static
|
||||
variable is used for that connection.
|
||||
On other scenarios, the user must solve this by taking into account that the current implementation of
|
||||
MQTTSNPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions
|
||||
to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int)
|
||||
*/
|
||||
static int mysock = INVALID_SOCKET;
|
||||
|
||||
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 lowlevel_sendPacketBuffer(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(mysock, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR)
|
||||
Socket_error("sendto", mysock);
|
||||
else
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int lowlevel_getdata(unsigned char* buf, int count)
|
||||
{
|
||||
int rc = recvfrom(mysock, buf, count, 0, NULL, NULL);
|
||||
//printf("received %d bytes count %d\n", rc, (int)count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
return >=0 for a socket descriptor, <0 for an error code
|
||||
*/
|
||||
int lowlevel_open()
|
||||
{
|
||||
mysock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (mysock == INVALID_SOCKET)
|
||||
return Socket_error("socket", mysock);
|
||||
|
||||
return mysock;
|
||||
}
|
||||
|
||||
int lowlevel_close()
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = shutdown(mysock, SHUT_WR);
|
||||
rc = close(mysock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
21
MQTTSNPacket/samples/linux/udp/lowlevel.h
Normal file
21
MQTTSNPacket/samples/linux/udp/lowlevel.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension
|
||||
*******************************************************************************/
|
||||
|
||||
int lowlevel_sendPacketBuffer(char* host, int port, unsigned char* buf, int buflen);
|
||||
int lowlevel_getdata(unsigned char* buf, int count);
|
||||
int lowlevel_open(void);
|
||||
int lowlevel_close(void);
|
||||
165
MQTTSNPacket/samples/linux/udp/pub0sub1.c
Normal file
165
MQTTSNPacket/samples/linux/udp/pub0sub1.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Normal topic name is automatically registered at subscription, then
|
||||
* a message is published and the node receives it itself
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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;
|
||||
unsigned char dup = 0;
|
||||
int qos = 1;
|
||||
unsigned char retained = 0;
|
||||
short packetid = 1;
|
||||
char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
unsigned short topicid;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "pub0sub1 MQTT-SN";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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;
|
||||
|
||||
|
||||
/* subscribe */
|
||||
printf("Subscribing\n");
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.long_.name = topicname;
|
||||
topic.data.long_.len = strlen(topic.data.long_.name);
|
||||
len = MQTTSNSerialize_subscribe(buf, buflen, 0, 2, packetid, &topic);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_getdata) == MQTTSN_SUBACK) /* wait for suback */
|
||||
{
|
||||
unsigned short submsgid;
|
||||
int granted_qos;
|
||||
unsigned char returncode;
|
||||
|
||||
rc = MQTTSNDeserialize_suback(&granted_qos, &topicid, &submsgid, &returncode, buf, buflen);
|
||||
if (granted_qos != 2 || returncode != 0)
|
||||
{
|
||||
printf("granted qos != 2, %d return code %d\n", granted_qos, returncode);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("suback topic id %d\n", topicid);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
printf("Publishing\n");
|
||||
/* publish with short name */
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.id = topicid;
|
||||
++packetid;
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for puback */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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, msgid %d topic id %d\n", packet_id, topic_id);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
printf("Receive publish\n");
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_getdata) == MQTTSN_PUBLISH)
|
||||
{
|
||||
unsigned short packet_id;
|
||||
int qos, payloadlen;
|
||||
unsigned char* payload;
|
||||
unsigned char dup, retained;
|
||||
MQTTSN_topicid pubtopic;
|
||||
|
||||
if (MQTTSNDeserialize_publish(&dup, &qos, &retained, &packet_id, &pubtopic,
|
||||
&payload, &payloadlen, buf, buflen) != 1)
|
||||
printf("Error deserializing publish\n");
|
||||
else
|
||||
printf("publish received, id %d qos %d\n", packet_id, qos);
|
||||
|
||||
if (qos == 1)
|
||||
{
|
||||
len = MQTTSNSerialize_puback(buf, buflen, pubtopic.data.id, packet_id, MQTTSN_RC_ACCEPTED);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
if (rc == 0)
|
||||
printf("puback sent\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
len = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
exit:
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
70
MQTTSNPacket/samples/linux/udp/qos-1pub.c
Normal file
70
MQTTSNPacket/samples/linux/udp/qos-1pub.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* A qos -1 message can be sent without connecting
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 3;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
/* publish with short name */
|
||||
topic.type = MQTTSN_TOPIC_TYPE_SHORT;
|
||||
memcpy(topic.data.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
72
MQTTSNPacket/samples/linux/udp/qos-1pub_extended.c
Normal file
72
MQTTSNPacket/samples/linux/udp/qos-1pub_extended.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Extension to the specs in which a node can send a normal (long) topic name inside the
|
||||
* payload area to avoid the registration process and the usage of short/predefined types
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 3;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.long_.name = topicname;
|
||||
topic.data.long_.len = strlen(topicname);
|
||||
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
94
MQTTSNPacket/samples/linux/udp/qos0pub.c
Normal file
94
MQTTSNPacket/samples/linux/udp/qos0pub.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 0;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
// char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
printf("rc %d from send packet for publish length %d\n", rc, len);
|
||||
|
||||
exit:
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
121
MQTTSNPacket/samples/linux/udp/qos0pub_register.c
Normal file
121
MQTTSNPacket/samples/linux/udp/qos0pub_register.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Normal topic name used to show registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
unsigned char buf[200];
|
||||
int buflen = sizeof(buf);
|
||||
MQTTSN_topicid topic;
|
||||
MQTTSNString topicstr;
|
||||
unsigned char* payload = (unsigned char*)"mypayload";
|
||||
int payloadlen = strlen((char*)payload);
|
||||
int len = 0;
|
||||
int dup = 0;
|
||||
int qos = 0;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
unsigned short topicid;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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;
|
||||
|
||||
/* register topic name */
|
||||
printf("Registering\n");
|
||||
topicstr.cstring = topicname;
|
||||
topicstr.lenstring.len = strlen(topicname);
|
||||
len = MQTTSNSerialize_register(buf, buflen, 0, packetid, &topicstr);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_getdata) == MQTTSN_REGACK) /* wait for regack */
|
||||
{
|
||||
unsigned short submsgid;
|
||||
unsigned char returncode;
|
||||
|
||||
rc = MQTTSNDeserialize_regack(&topicid, &submsgid, &returncode, buf, buflen);
|
||||
if (returncode != 0)
|
||||
{
|
||||
printf("return code %d\n", returncode);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("regack topic id %d\n", topicid);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
/* publish with obtained id */
|
||||
printf("Publishing\n");
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.id = topicid;
|
||||
++packetid;
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
printf("rc %d from send packet for publish length %d\n", rc, len);
|
||||
|
||||
exit:
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
107
MQTTSNPacket/samples/linux/udp/qos1pub.c
Normal file
107
MQTTSNPacket/samples/linux/udp/qos1pub.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "lowlevel.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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;
|
||||
short packetid = 1;
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
|
||||
mysock = lowlevel_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen - len, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for puback */
|
||||
if (MQTTSNPacket_read(buf, buflen, lowlevel_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 = lowlevel_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
exit:
|
||||
lowlevel_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
165
MQTTSNPacket/samples/pub0sub1.c
Normal file
165
MQTTSNPacket/samples/pub0sub1.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Normal topic name is automatically registered at subscription, then
|
||||
* a message is published and the node receives it itself
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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;
|
||||
unsigned char dup = 0;
|
||||
int qos = 1;
|
||||
unsigned char retained = 0;
|
||||
short packetid = 1;
|
||||
char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
unsigned short topicid;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "pub0sub1 MQTT-SN";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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;
|
||||
|
||||
|
||||
/* subscribe */
|
||||
printf("Subscribing\n");
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.long_.name = topicname;
|
||||
topic.data.long_.len = strlen(topic.data.long_.name);
|
||||
len = MQTTSNSerialize_subscribe(buf, buflen, 0, 2, packetid, &topic);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_SUBACK) /* wait for suback */
|
||||
{
|
||||
unsigned short submsgid;
|
||||
int granted_qos;
|
||||
unsigned char returncode;
|
||||
|
||||
rc = MQTTSNDeserialize_suback(&granted_qos, &topicid, &submsgid, &returncode, buf, buflen);
|
||||
if (granted_qos != 2 || returncode != 0)
|
||||
{
|
||||
printf("granted qos != 2, %d return code %d\n", granted_qos, returncode);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("suback topic id %d\n", topicid);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
printf("Publishing\n");
|
||||
/* publish with short name */
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.id = topicid;
|
||||
++packetid;
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for puback */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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, msgid %d topic id %d\n", packet_id, topic_id);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
printf("Receive publish\n");
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_PUBLISH)
|
||||
{
|
||||
unsigned short packet_id;
|
||||
int qos, payloadlen;
|
||||
unsigned char* payload;
|
||||
unsigned char dup, retained;
|
||||
MQTTSN_topicid pubtopic;
|
||||
|
||||
if (MQTTSNDeserialize_publish(&dup, &qos, &retained, &packet_id, &pubtopic,
|
||||
&payload, &payloadlen, buf, buflen) != 1)
|
||||
printf("Error deserializing publish\n");
|
||||
else
|
||||
printf("publish received, id %d qos %d\n", packet_id, qos);
|
||||
|
||||
if (qos == 1)
|
||||
{
|
||||
len = MQTTSNSerialize_puback(buf, buflen, pubtopic.data.id, packet_id, MQTTSN_RC_ACCEPTED);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
if (rc == 0)
|
||||
printf("puback sent\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
len = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
exit:
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
70
MQTTSNPacket/samples/qos-1pub.c
Normal file
70
MQTTSNPacket/samples/qos-1pub.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* A qos -1 message can be sent without connecting
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 3;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
/* publish with short name */
|
||||
topic.type = MQTTSN_TOPIC_TYPE_SHORT;
|
||||
memcpy(topic.data.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
72
MQTTSNPacket/samples/qos-1pub_extended.c
Normal file
72
MQTTSNPacket/samples/qos-1pub_extended.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Extension to the specs in which a node can send a normal (long) topic name inside the
|
||||
* payload area to avoid the registration process and the usage of short/predefined types
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 3;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.long_.name = topicname;
|
||||
topic.data.long_.len = strlen(topicname);
|
||||
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
94
MQTTSNPacket/samples/qos0pub.c
Normal file
94
MQTTSNPacket/samples/qos0pub.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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 = 0;
|
||||
int retained = 0;
|
||||
short packetid = 0;
|
||||
// char *topicname = "a long topic name";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
printf("rc %d from send packet for publish length %d\n", rc, len);
|
||||
|
||||
exit:
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
131
MQTTSNPacket/samples/qos0pub_register.c
Normal file
131
MQTTSNPacket/samples/qos0pub_register.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Normal topic name used to show registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
unsigned char buf[500];
|
||||
int buflen = sizeof(buf);
|
||||
MQTTSN_topicid topic;
|
||||
MQTTSNString topicstr;
|
||||
int len = 0;
|
||||
int retained = 0;
|
||||
char *topicname = "iot-2/evt/status/fmt/json";
|
||||
char *host = "127.0.0.1";
|
||||
int port = 20000;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
unsigned short topicid;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "d:quickstart:udptest:9002f7f1ad23";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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
|
||||
{
|
||||
printf("could not connect to gateway\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* register topic name */
|
||||
printf("Registering\n");
|
||||
int packetid = 1;
|
||||
topicstr.cstring = topicname;
|
||||
topicstr.lenstring.len = strlen(topicname);
|
||||
len = MQTTSNSerialize_register(buf, buflen, 0, packetid, &topicstr);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_REGACK) /* wait for regack */
|
||||
{
|
||||
unsigned short submsgid;
|
||||
unsigned char returncode;
|
||||
|
||||
rc = MQTTSNDeserialize_regack(&topicid, &submsgid, &returncode, buf, buflen);
|
||||
if (returncode != 0)
|
||||
{
|
||||
printf("return code %d\n", returncode);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("regack topic id %d\n", topicid);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (1)
|
||||
{
|
||||
/* publish with obtained id */
|
||||
printf("Publishing\n");
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.id = topicid;
|
||||
static const char* joypos[] = {"SN-LEFT", "SN-RIGHT", "SN-CENTRE", "SN-UP", "SN-DOWN"};
|
||||
|
||||
unsigned char payload[250];
|
||||
int payloadlen = sprintf((char*)payload,
|
||||
"{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}",
|
||||
(rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) * 2.0, (rand() % 10) + 18.0, joypos[rand() % 5], (rand() % 10) * 30.0, (rand() % 10) * 30.0);
|
||||
len = MQTTSNSerialize_publish(buf, buflen, 0, 0, retained, 0, topic, payload, payloadlen);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
printf("rc %d from send packet for publish length %d\n", rc, len);
|
||||
}
|
||||
sleep(1); // Publish a message every second
|
||||
}
|
||||
exit:
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
107
MQTTSNPacket/samples/qos1pub.c
Normal file
107
MQTTSNPacket/samples/qos1pub.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - clarifications and/or documentation extension
|
||||
*
|
||||
* Description:
|
||||
* Short topic name used to avoid registration process
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "transport.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int mysock;
|
||||
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;
|
||||
short packetid = 1;
|
||||
char *host = "127.0.0.1";
|
||||
int port = 1883;
|
||||
MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer;
|
||||
|
||||
mysock = transport_open();
|
||||
if(mysock < 0)
|
||||
return mysock;
|
||||
|
||||
if (argc > 1)
|
||||
host = argv[1];
|
||||
|
||||
if (argc > 2)
|
||||
port = atoi(argv[2]);
|
||||
|
||||
printf("Sending to hostname %s port %d\n", host, port);
|
||||
|
||||
options.clientID.cstring = "myclientid";
|
||||
len = MQTTSNSerialize_connect(buf, buflen, &options);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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.short_name, "tt", 2);
|
||||
len = MQTTSNSerialize_publish(buf, buflen - len, dup, qos, retained, packetid,
|
||||
topic, payload, payloadlen);
|
||||
rc = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
/* wait for puback */
|
||||
if (MQTTSNPacket_read(buf, buflen, transport_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 = transport_sendPacketBuffer(host, port, buf, len);
|
||||
|
||||
exit:
|
||||
transport_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
141
MQTTSNPacket/samples/transport.c
Normal file
141
MQTTSNPacket/samples/transport.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension
|
||||
*******************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
This simple low-level implementation assumes a single connection for a single thread. Thus, a static
|
||||
variable is used for that connection.
|
||||
On other scenarios, the user must solve this by taking into account that the current implementation of
|
||||
MQTTSNPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions
|
||||
to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int)
|
||||
*/
|
||||
static int mysock = INVALID_SOCKET;
|
||||
|
||||
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 transport_sendPacketBuffer(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(mysock, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR)
|
||||
Socket_error("sendto", mysock);
|
||||
else
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int transport_getdata(unsigned char* buf, int count)
|
||||
{
|
||||
int rc = recvfrom(mysock, buf, count, 0, NULL, NULL);
|
||||
//printf("received %d bytes count %d\n", rc, (int)count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
return >=0 for a socket descriptor, <0 for an error code
|
||||
*/
|
||||
int transport_open()
|
||||
{
|
||||
mysock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (mysock == INVALID_SOCKET)
|
||||
return Socket_error("socket", mysock);
|
||||
|
||||
return mysock;
|
||||
}
|
||||
|
||||
int transport_close()
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = shutdown(mysock, SHUT_WR);
|
||||
rc = close(mysock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
21
MQTTSNPacket/samples/transport.h
Normal file
21
MQTTSNPacket/samples/transport.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
* Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension
|
||||
*******************************************************************************/
|
||||
|
||||
int transport_sendPacketBuffer(char* host, int port, unsigned char* buf, int buflen);
|
||||
int transport_getdata(unsigned char* buf, int count);
|
||||
int transport_open(void);
|
||||
int transport_close(void);
|
||||
74
MQTTSNPacket/src/MQTTSNConnect.h
Normal file
74
MQTTSNPacket/src/MQTTSNConnect.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTSNCONNECT_H_
|
||||
#define MQTTSNCONNECT_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** The eyecatcher for this structure. must be MQSC. */
|
||||
char struct_id[4];
|
||||
/** The version number of this structure. Must be 0.
|
||||
*/
|
||||
int struct_version;
|
||||
MQTTSNString clientID;
|
||||
unsigned short duration;
|
||||
unsigned char cleansession;
|
||||
unsigned char willFlag;
|
||||
} MQTTSNPacket_connectData;
|
||||
|
||||
#define MQTTSNPacket_connectData_initializer { {'M', 'Q', 'S', 'C'}, 0, {NULL, {0, NULL}}, 10, 1, 0 }
|
||||
|
||||
int MQTTSNSerialize_connect(unsigned char* buf, int buflen, MQTTSNPacket_connectData* options);
|
||||
int MQTTSNDeserialize_connect(MQTTSNPacket_connectData* data, unsigned char* buf, int len);
|
||||
|
||||
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, MQTTSNString clientid);
|
||||
int MQTTSNDeserialize_pingreq(MQTTSNString* clientID, unsigned char* buf, int len);
|
||||
|
||||
int MQTTSNSerialize_pingresp(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_pingresp(unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willmsg(unsigned char* buf, int buflen, MQTTSNString willMsg);
|
||||
int MQTTSNDeserialize_willmsg(MQTTSNString* willMsg, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willmsgreq(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_willmsgreq(unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willmsgupd(unsigned char* buf, int buflen, MQTTSNString willMsg);
|
||||
int MQTTSNDeserialize_willmsgupd(MQTTSNString* willMsg, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc);
|
||||
int MQTTSNDeserialize_willmsgresp(int* resp_rc, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willtopic(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic);
|
||||
int MQTTSNDeserialize_willtopic(int* willQoS, unsigned char* willRetain, MQTTSNString* willTopic, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willtopicreq(unsigned char* buf, int buflen);
|
||||
int MQTTSNDeserialize_willtopicreq(unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willtopicupd(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic);
|
||||
int MQTTSNDeserialize_willtopicupd(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc);
|
||||
int MQTTSNDeserialize_willtopicresp(int* resp_rc, unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNCONNECT_H_ */
|
||||
478
MQTTSNPacket/src/MQTTSNConnectClient.c
Normal file
478
MQTTSNPacket/src/MQTTSNConnectClient.c
Normal file
@@ -0,0 +1,478 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014, 2015 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
|
||||
* Nicholas Humfrey - Reformatting to make more consistent; bug 453862
|
||||
*******************************************************************************/
|
||||
|
||||
#include "MQTTSNPacket.h"
|
||||
#include "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
|
||||
* @param options the options to be used to build the connect packet
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_connectLength(MQTTSNPacket_connectData* options)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
len = 5 + MQTTSNstrlen(options->clientID);
|
||||
FUNC_EXIT_RC(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the connect options into the buffer.
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param len the length in bytes of the supplied buffer
|
||||
* @param options the options to be used to build the connect packet
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_connect(unsigned char* buf, int buflen, MQTTSNPacket_connectData* options)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_connectLength(options))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_CONNECT); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.cleanSession = options->cleansession;
|
||||
flags.bits.will = options->willFlag;
|
||||
writeChar(&ptr, flags.all);
|
||||
writeChar(&ptr, 0x01); /* protocol ID */
|
||||
writeInt(&ptr, options->duration);
|
||||
writeMQTTSNString(&ptr, options->clientID);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into connack data - return code
|
||||
* @param connack_rc returned integer value of the connack return code
|
||||
* @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_connack(int* connack_rc, 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 - buf < 3)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_CONNACK)
|
||||
goto exit;
|
||||
|
||||
*connack_rc = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT disconnect packet (without length field)
|
||||
* @param duration the parameter used for the disconnect
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_disconnectLength(int duration)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
len = (duration >= 0) ? 3 : 1;
|
||||
FUNC_EXIT_RC(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 duration optional duration, not added to packet if < 0
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_disconnect(unsigned char* buf, int buflen, int duration)
|
||||
{
|
||||
int rc = -1;
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_disconnectLength(duration))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_DISCONNECT); /* write message type */
|
||||
|
||||
if (duration >= 0)
|
||||
writeInt(&ptr, duration);
|
||||
|
||||
rc = ptr - buf;
|
||||
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, MQTTSNString clientid)
|
||||
{
|
||||
int rc = -1;
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNstrlen(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 willtopic or 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_willtopic1(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic,
|
||||
enum MQTTSN_msgTypes packet_type)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNstrlen(willTopic) + 2)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, packet_type); /* 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 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, unsigned char willRetain, MQTTSNString willTopic)
|
||||
{
|
||||
return MQTTSNSerialize_willtopic1(buf, buflen, willQoS, willRetain, willTopic, MQTTSN_WILLTOPICUPD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willtopic 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_willtopic(unsigned char* buf, int buflen, int willQoS, unsigned char willRetain, MQTTSNString willTopic)
|
||||
{
|
||||
return MQTTSNSerialize_willtopic1(buf, buflen, willQoS, willRetain, willTopic, MQTTSN_WILLTOPIC);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willmsg or willmsgupd 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
|
||||
* @param willMsg the will message
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willmsg1(unsigned char* buf, int buflen, MQTTSNString willMsg, enum MQTTSN_msgTypes packet_type)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = -1;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNstrlen(willMsg) + 1)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, packet_type); /* write message type */
|
||||
|
||||
writeMQTTSNString(&ptr, willMsg);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a willmsg 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_willmsg(unsigned char* buf, int buflen, MQTTSNString willMsg)
|
||||
{
|
||||
return MQTTSNSerialize_willmsg1(buf, buflen, willMsg, MQTTSN_WILLMSG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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, MQTTSNString willMsg)
|
||||
{
|
||||
return MQTTSNSerialize_willmsg1(buf, buflen, willMsg, MQTTSN_WILLMSGUPD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willtopicresp data - return code
|
||||
* @param connack_rc returned integer value of the return code
|
||||
* @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_willtopicresp(int* resp_rc, 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 - buf < 3)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_WILLTOPICRESP)
|
||||
goto exit;
|
||||
|
||||
*resp_rc = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willmsgresp data - return code
|
||||
* @param connack_rc returned integer value of the return code
|
||||
* @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_willmsgresp(int* resp_rc, 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 - buf < 3)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_WILLMSGRESP)
|
||||
goto exit;
|
||||
|
||||
*resp_rc = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
430
MQTTSNPacket/src/MQTTSNConnectServer.c
Normal file
430
MQTTSNPacket/src/MQTTSNConnectServer.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
#include "MQTTSNPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
#define min(a, b) ((a < b) ? 1 : 0)
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into connect data structure
|
||||
* @param data 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_connect(MQTTSNPacket_connectData* data, unsigned char* buf, int len)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = &buf[len];
|
||||
int rc = 0;
|
||||
int version;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, len, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata < 2)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_CONNECT)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
data->cleansession = flags.bits.cleanSession;
|
||||
data->willFlag = flags.bits.will;
|
||||
|
||||
if ((version = (int)readChar(&curdata)) != 1) /* Protocol version */
|
||||
goto exit;
|
||||
|
||||
data->duration = readInt(&curdata);
|
||||
|
||||
if (!readMQTTSNString(&data->clientID, &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the connack 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
|
||||
* @param connack_rc the integer connack return code to be used
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_connack(unsigned char* buf, int buflen, int connack_rc)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 3)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
|
||||
writeChar(&ptr, MQTTSN_CONNACK);
|
||||
writeChar(&ptr, connack_rc);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
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(MQTTSNString* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willtopic or willtopicupd data structure
|
||||
* @param data 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_willtopic1(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len,
|
||||
enum MQTTSN_msgTypes packet_type)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
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 > buf + len)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != packet_type)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*willQoS = flags.bits.QoS;
|
||||
*willRetain = flags.bits.retain;
|
||||
|
||||
if (!readMQTTSNString(willTopic, &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willtopic data structure
|
||||
* @param data 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_willtopic(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len)
|
||||
{
|
||||
return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willtopic data structure
|
||||
* @param data 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_willtopicupd(int *willQoS, unsigned char *willRetain, MQTTSNString* willTopic, unsigned char* buf, int len)
|
||||
{
|
||||
return MQTTSNDeserialize_willtopic1(willQoS, willRetain, willTopic, buf, len, MQTTSN_WILLTOPICUPD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willmsg or willmsgupd data
|
||||
* @param willMsg the will message to be retrieved
|
||||
* @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_willmsg1(MQTTSNString* willMsg, unsigned char* buf, int len, enum MQTTSN_msgTypes packet_type)
|
||||
{
|
||||
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 > buf + len)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != packet_type)
|
||||
goto exit;
|
||||
|
||||
if (!readMQTTSNString(willMsg, &curdata, enddata))
|
||||
goto exit;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willmsg data
|
||||
* @param willMsg the will message to be retrieved
|
||||
* @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_willmsg(MQTTSNString* willMsg, unsigned char* buf, int len)
|
||||
{
|
||||
return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into willmsgupd data
|
||||
* @param willMsg the will message to be retrieved
|
||||
* @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_willmsgupd(MQTTSNString* willMsg, unsigned char* buf, int len)
|
||||
{
|
||||
return MQTTSNDeserialize_willmsg1(willMsg, buf, len, MQTTSN_WILLMSGUPD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the willtopicresp 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
|
||||
* @param rc the integer return code to be used
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willtopicresp(unsigned char* buf, int buflen, int resp_rc)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 3)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLTOPICRESP);
|
||||
writeChar(&ptr, resp_rc);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the willmsgresp 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
|
||||
* @param rc the integer return code to be used
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_willmsgresp(unsigned char* buf, int buflen, int resp_rc)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen < 3)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ptr += MQTTSNPacket_encode(ptr, 3); /* write length */
|
||||
writeChar(&ptr, MQTTSN_WILLMSGRESP);
|
||||
writeChar(&ptr, resp_rc);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
225
MQTTSNPacket/src/MQTTSNDeserializePublish.c
Normal file
225
MQTTSNPacket/src/MQTTSNDeserializePublish.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
#include "MQTTSNPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
#define min(a, b) ((a < b) ? 1 : 0)
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into publish data
|
||||
* @param dup returned integer - the MQTT dup flag
|
||||
* @param qos returned integer - the MQTT QoS value
|
||||
* @param retained returned integer - the MQTT retained flag
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param topicName returned MQTTSNString - the MQTT topic in the publish
|
||||
* @param payload returned byte buffer - the MQTT publish payload
|
||||
* @param payloadlen returned integer - the length of the MQTT payload
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTSN_topicid* topic,
|
||||
unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_PUBLISH)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*dup = flags.bits.dup;
|
||||
*qos = flags.bits.QoS;
|
||||
*retained = flags.bits.retain;
|
||||
|
||||
topic->type = flags.bits.topicIdType;
|
||||
if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL && *qos == 3)
|
||||
{
|
||||
/* special arrangement for long topic names in QoS -1 publishes. The length of the topic is in the topicid field */
|
||||
topic->data.long_.len = readInt(&curdata);
|
||||
}
|
||||
else if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL || topic->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
topic->data.id = readInt(&curdata);
|
||||
else
|
||||
{
|
||||
topic->data.short_name[0] = readChar(&curdata);
|
||||
topic->data.short_name[1] = readChar(&curdata);
|
||||
}
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
if (topic->type == MQTTSN_TOPIC_TYPE_NORMAL && *qos == 3)
|
||||
{
|
||||
topic->data.long_.name = (char*)curdata;
|
||||
curdata += topic->data.long_.len;
|
||||
}
|
||||
|
||||
*payloadlen = enddata - curdata;
|
||||
*payload = curdata;
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int MQTTSNDeserialize_puback(unsigned short* topicid, unsigned short* packetid,
|
||||
unsigned char* returncode, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_PUBACK)
|
||||
goto exit;
|
||||
|
||||
*topicid = readInt(&curdata);
|
||||
*packetid = readInt(&curdata);
|
||||
*returncode = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into an ack
|
||||
* @param packettype returned integer - the MQTT packet type
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success, 0 is failure
|
||||
*/
|
||||
int MQTTSNDeserialize_ack(unsigned char* type, unsigned short* packetid, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
*type = readChar(&curdata);
|
||||
if (*type != MQTTSN_PUBREL && *type != MQTTSN_PUBREC && *type != MQTTSN_PUBCOMP)
|
||||
goto exit;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into register data
|
||||
* @param topicid returned topic id
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param topicName returned MQTTSNString - the MQTT topic in the register
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTSNString* topicname,
|
||||
unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_REGISTER)
|
||||
goto exit;
|
||||
|
||||
*topicid = readInt(&curdata);
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
topicname->lenstring.data = (char*)curdata;
|
||||
topicname->lenstring.len = enddata - curdata;
|
||||
topicname->cstring = NULL;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into register data
|
||||
* @param topicid returned topic id
|
||||
* @param packetid returned integer - the MQTT packet identifier
|
||||
* @param return_code returned integer return code
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code,
|
||||
unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_REGACK)
|
||||
goto exit;
|
||||
|
||||
*topicid = readInt(&curdata);
|
||||
*packetid = readInt(&curdata);
|
||||
*return_code = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
271
MQTTSNPacket/src/MQTTSNPacket.c
Normal file
271
MQTTSNPacket/src/MQTTSNPacket.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
#include "MQTTSNPacket.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static char* packet_names[] =
|
||||
{
|
||||
"ADVERTISE", "SEARCHGW", "GWINFO", "RESERVED", "CONNECT", "CONNACK",
|
||||
"WILLTOPICREQ", "WILLTOPIC", "WILLMSGREQ", "WILLMSG", "REGISTER", "REGACK",
|
||||
"PUBLISH", "PUBACK", "PUBCOMP", "PUBREC", "PUBREL", "RESERVED",
|
||||
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
|
||||
"DISCONNECT", "RESERVED", "WILLTOPICUPD", "WILLTOPICRESP", "WILLMSGUPD",
|
||||
"WILLMSGRESP"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a character string representing the packet name given a MsgType code
|
||||
* @param code MsgType code
|
||||
* @return the corresponding packet name
|
||||
*/
|
||||
char* MQTTSNPacket_name(int code)
|
||||
{
|
||||
return (code >= 0 && code <= MQTTSN_WILLMSGRESP) ? packet_names[code] : "UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the full packet length including length field
|
||||
* @param length the length of the MQTT-SN packet without the length field
|
||||
* @return the total length of the MQTT-SN packet including the length field
|
||||
*/
|
||||
int MQTTSNPacket_len(int length)
|
||||
{
|
||||
return (length > 255) ? length + 3 : length + 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes the MQTT-SN message length
|
||||
* @param buf the buffer into which the encoded data is written
|
||||
* @param length the length to be encoded
|
||||
* @return the number of bytes written to the buffer
|
||||
*/
|
||||
int MQTTSNPacket_encode(unsigned char* buf, int length)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (length > 255)
|
||||
{
|
||||
buf[rc++] = 0x01;
|
||||
writeInt(&buf, length);
|
||||
rc += 2;
|
||||
}
|
||||
else
|
||||
buf[rc++] = length;
|
||||
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the MQTT-SN packet length from received data
|
||||
* @param getcharfn pointer to function to read the next character from the data source
|
||||
* @param value the decoded length returned
|
||||
* @return the number of bytes read from the socket
|
||||
*/
|
||||
int MQTTSNPacket_decode(unsigned char* buf, int buflen, int* value)
|
||||
{
|
||||
int len = MQTTSNPACKET_READ_ERROR;
|
||||
#define MAX_NO_OF_LENGTH_BYTES 3
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (buflen <= 0)
|
||||
goto exit;
|
||||
|
||||
if (buf[0] == 1)
|
||||
{
|
||||
unsigned char* bufptr = &buf[1];
|
||||
if (buflen < 3)
|
||||
goto exit;
|
||||
*value = readInt(&bufptr);
|
||||
len = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value = buf[0];
|
||||
len = 1;
|
||||
}
|
||||
exit:
|
||||
FUNC_EXIT_RC(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return the integer value calculated
|
||||
*/
|
||||
int readInt(unsigned char** pptr)
|
||||
{
|
||||
unsigned char* ptr = *pptr;
|
||||
int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
|
||||
*pptr += 2;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads one character from the input buffer.
|
||||
* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
|
||||
* @return the character read
|
||||
*/
|
||||
char readChar(unsigned char** pptr)
|
||||
{
|
||||
char c = **pptr;
|
||||
(*pptr)++;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes one character to an output buffer.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param c the character to write
|
||||
*/
|
||||
void writeChar(unsigned char** pptr, char c)
|
||||
{
|
||||
**pptr = (unsigned char)c;
|
||||
(*pptr)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes an integer as 2 bytes to an output buffer.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param anInt the integer to write: 0 to 65535
|
||||
*/
|
||||
void writeInt(unsigned char** pptr, int anInt)
|
||||
{
|
||||
**pptr = (unsigned char)(anInt / 256);
|
||||
(*pptr)++;
|
||||
**pptr = (unsigned char)(anInt % 256);
|
||||
(*pptr)++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes a "UTF" string to an output buffer. Converts C string to length-delimited.
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param string the C string to write
|
||||
*/
|
||||
void writeCString(unsigned char** pptr, char* string)
|
||||
{
|
||||
int len = strlen(string);
|
||||
memcpy(*pptr, string, len);
|
||||
*pptr += len;
|
||||
}
|
||||
|
||||
|
||||
int getLenStringLen(char* ptr)
|
||||
{
|
||||
int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void writeMQTTSNString(unsigned char** pptr, MQTTSNString MQTTSNString)
|
||||
{
|
||||
if (MQTTSNString.lenstring.len > 0)
|
||||
{
|
||||
memcpy(*pptr, MQTTSNString.lenstring.data, MQTTSNString.lenstring.len);
|
||||
*pptr += MQTTSNString.lenstring.len;
|
||||
}
|
||||
else if (MQTTSNString.cstring)
|
||||
writeCString(pptr, MQTTSNString.cstring);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param MQTTSNString the MQTTSNString structure into which the data is to be read
|
||||
* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
|
||||
* @param enddata pointer to the end of the data: do not read beyond
|
||||
* @return 1 if successful, 0 if not
|
||||
*/
|
||||
int readMQTTSNString(MQTTSNString* MQTTSNString, unsigned char** pptr, unsigned char* enddata)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
MQTTSNString->lenstring.len = enddata - *pptr;
|
||||
if (MQTTSNString->lenstring.len > 0)
|
||||
{
|
||||
MQTTSNString->lenstring.data = (char*)*pptr;
|
||||
*pptr += MQTTSNString->lenstring.len;
|
||||
}
|
||||
else
|
||||
MQTTSNString->lenstring.data = NULL;
|
||||
MQTTSNString->cstring = NULL;
|
||||
rc = 1;
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the length of the MQTTSNString - C string if there is one, otherwise the length delimited string
|
||||
* @param MQTTSNString the string to return the length of
|
||||
* @return the length of the string
|
||||
*/
|
||||
int MQTTSNstrlen(MQTTSNString MQTTSNString)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (MQTTSNString.cstring)
|
||||
rc = strlen(MQTTSNString.cstring);
|
||||
else
|
||||
rc = MQTTSNString.lenstring.len;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to read packet data from some source into a buffer
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @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 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;
|
||||
int datalen = 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 */
|
||||
|
||||
rc = buf[lenlen]; /* return the packet type */
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
150
MQTTSNPacket/src/MQTTSNPacket.h
Normal file
150
MQTTSNPacket/src/MQTTSNPacket.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef MQTTSNPACKET_H_
|
||||
#define MQTTSNPACKET_H_
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum errors
|
||||
{
|
||||
MQTTSNPACKET_BUFFER_TOO_SHORT = -2,
|
||||
MQTTSNPACKET_READ_ERROR = -1,
|
||||
MQTTSNPACKET_READ_COMPLETE,
|
||||
};
|
||||
|
||||
#define MQTTSN_PROTOCOL_VERSION 0x01
|
||||
|
||||
enum MQTTSN_connackCodes
|
||||
{
|
||||
MQTTSN_RC_ACCEPTED,
|
||||
MQTTSN_RC_REJECTED_CONGESTED,
|
||||
MQTTSN_RC_REJECTED_INVALID_TOPIC_ID,
|
||||
};
|
||||
|
||||
enum MQTTSN_topicTypes
|
||||
{
|
||||
MQTTSN_TOPIC_TYPE_NORMAL, /* topic id in publish, topic name in subscribe */
|
||||
MQTTSN_TOPIC_TYPE_PREDEFINED,
|
||||
MQTTSN_TOPIC_TYPE_SHORT,
|
||||
};
|
||||
|
||||
|
||||
enum MQTTSN_msgTypes
|
||||
{
|
||||
MQTTSN_ADVERTISE, MQTTSN_SEARCHGW, MQTTSN_GWINFO, MQTTSN_RESERVED1,
|
||||
MQTTSN_CONNECT, MQTTSN_CONNACK,
|
||||
MQTTSN_WILLTOPICREQ, MQTTSN_WILLTOPIC, MQTTSN_WILLMSGREQ, MQTTSN_WILLMSG,
|
||||
MQTTSN_REGISTER, MQTTSN_REGACK,
|
||||
MQTTSN_PUBLISH, MQTTSN_PUBACK, MQTTSN_PUBCOMP, MQTTSN_PUBREC, MQTTSN_PUBREL, MQTTSN_RESERVED2,
|
||||
MQTTSN_SUBSCRIBE, MQTTSN_SUBACK, MQTTSN_UNSUBSCRIBE, MQTTSN_UNSUBACK,
|
||||
MQTTSN_PINGREQ, MQTTSN_PINGRESP,
|
||||
MQTTSN_DISCONNECT, MQTTSN_RESERVED3,
|
||||
MQTTSN_WILLTOPICUPD, MQTTSN_WILLTOPICRESP, MQTTSN_WILLMSGUPD, MQTTSN_WILLMSGRESP,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum MQTTSN_topicTypes type;
|
||||
union
|
||||
{
|
||||
unsigned short id;
|
||||
char short_name[2];
|
||||
struct
|
||||
{
|
||||
char* name;
|
||||
int len;
|
||||
} long_;
|
||||
} data;
|
||||
} MQTTSN_topicid;
|
||||
|
||||
|
||||
/**
|
||||
* Bitfields for the MQTT-SN flags byte.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
unsigned char all;
|
||||
#if defined(REVERSED)
|
||||
struct
|
||||
{
|
||||
int dup: 1;
|
||||
unsigned int QoS : 2;
|
||||
unsigned int retain : 1;
|
||||
unsigned int will : 1;
|
||||
unsigned int cleanSession : 1;
|
||||
unsigned int topicIdType : 2;
|
||||
} bits;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
unsigned int topicIdType : 2;
|
||||
unsigned int cleanSession : 1;
|
||||
unsigned int will : 1;
|
||||
unsigned int retain : 1;
|
||||
unsigned int QoS : 2;
|
||||
int dup: 1;
|
||||
} bits;
|
||||
#endif
|
||||
} MQTTSNFlags;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int len;
|
||||
char* data;
|
||||
} MQTTSNLenString;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* cstring;
|
||||
MQTTSNLenString lenstring;
|
||||
} MQTTSNString;
|
||||
|
||||
#define MQTTSNString_initializer {NULL, {0, NULL}}
|
||||
|
||||
int MQTTSNstrlen(MQTTSNString mqttsnstring);
|
||||
|
||||
#include "MQTTSNConnect.h"
|
||||
#include "MQTTSNPublish.h"
|
||||
#include "MQTTSNSubscribe.h"
|
||||
#include "MQTTSNUnsubscribe.h"
|
||||
#include "MQTTSNSearch.h"
|
||||
|
||||
char* MQTTSNPacket_name(int ptype);
|
||||
int MQTTSNPacket_len(int length);
|
||||
|
||||
int MQTTSNPacket_encode(unsigned char* buf, int length);
|
||||
int MQTTSNPacket_decode(unsigned char* buf, int buflen, int* value);
|
||||
|
||||
int readInt(unsigned char** pptr);
|
||||
char readChar(unsigned char** pptr);
|
||||
void writeChar(unsigned char** pptr, char c);
|
||||
void writeInt(unsigned char** pptr, int anInt);
|
||||
int readMQTTSNString(MQTTSNString* mqttstring, unsigned char** pptr, unsigned char* enddata);
|
||||
void writeCString(unsigned char** pptr, char* string);
|
||||
void writeMQTTSNString(unsigned char** pptr, MQTTSNString mqttstring);
|
||||
|
||||
int MQTTSNPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
|
||||
|
||||
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* MQTTSNPACKET_H_ */
|
||||
45
MQTTSNPacket/src/MQTTSNPublish.h
Normal file
45
MQTTSNPacket/src/MQTTSNPublish.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#if !defined(MQTTSNPUBLISH_H_)
|
||||
#define MQTTSNPUBLISH_H_
|
||||
|
||||
int MQTTSNSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
|
||||
MQTTSN_topicid topic, unsigned char* payload, int payloadlen);
|
||||
int MQTTSNDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid,
|
||||
MQTTSN_topicid* topic, unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
|
||||
|
||||
int MQTTSNSerialize_puback(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char returncode);
|
||||
int MQTTSNDeserialize_puback(unsigned short* topicid, unsigned short* packetid,
|
||||
unsigned char* returncode, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_pubrec(unsigned char* buf, int buflen, unsigned short packetid);
|
||||
int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
|
||||
|
||||
int MQTTSNDeserialize_ack(unsigned char* packettype, unsigned short* packetid, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
MQTTSNString* topicname);
|
||||
int MQTTSNDeserialize_register(unsigned short* topicid, unsigned short* packetid, MQTTSNString* topicname,
|
||||
unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char return_code);
|
||||
int MQTTSNDeserialize_regack(unsigned short* topicid, unsigned short* packetid, unsigned char* return_code,
|
||||
unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNPUBLISH_H_ */
|
||||
31
MQTTSNPacket/src/MQTTSNSearch.h
Normal file
31
MQTTSNPacket/src/MQTTSNSearch.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#if !defined(MQTTSNSEARCH_H_)
|
||||
#define MQTTSNSEARCH_H_
|
||||
|
||||
int MQTTSNSerialize_advertise(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short duration);
|
||||
int MQTTSNDeserialize_advertise(unsigned char* gatewayid, unsigned short* duration, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_searchgw(unsigned char* buf, int buflen, unsigned char radius);
|
||||
int MQTTSNDeserialize_searchgw(unsigned char* radius, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_gwinfo(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short gatewayaddress_len,
|
||||
unsigned char* gatewayaddress);
|
||||
int MQTTSNDeserialize_gwinfo(unsigned char* gatewayid, unsigned short* gatewayaddress_len, unsigned char** gatewayaddress,
|
||||
unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNSEARCH_H_ */
|
||||
126
MQTTSNPacket/src/MQTTSNSearchClient.c
Normal file
126
MQTTSNPacket/src/MQTTSNSearchClient.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into advertise data
|
||||
* @param gatewayid the returned gateway id
|
||||
* @param duration the returned duration - the time interval until the next advertise will be sent
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_advertise(unsigned char* gatewayid, unsigned short* duration, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_ADVERTISE)
|
||||
goto exit;
|
||||
|
||||
*gatewayid = readChar(&curdata);
|
||||
*duration = readInt(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied searchgw data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param radius the broadcast radius of this message
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_searchgw(unsigned char* buf, int buflen, unsigned char radius)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(2)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_SEARCHGW); /* write message type */
|
||||
|
||||
writeChar(&ptr, radius);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into gwinfo data
|
||||
* @param gatewayid the returned gateway id
|
||||
* @param gatewayaddress_len the optional returned length of the gateway address (0 if none)
|
||||
* @param gatewayaddress the optional returned gateway address (set to NULL if none)
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_gwinfo(unsigned char* gatewayid, unsigned short* gatewayaddress_len,
|
||||
unsigned char** gatewayaddress, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_GWINFO)
|
||||
goto exit;
|
||||
|
||||
*gatewayid = readChar(&curdata);
|
||||
|
||||
*gatewayaddress_len = enddata - curdata;
|
||||
*gatewayaddress = (gatewayaddress_len > 0) ? curdata : NULL;
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
128
MQTTSNPacket/src/MQTTSNSearchServer.c
Normal file
128
MQTTSNPacket/src/MQTTSNSearchServer.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied advertise data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param radius the broadcast radius of this message
|
||||
* @param duration - the time interval until the next advertise will be sent
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_advertise(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short duration)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(4)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_ADVERTISE); /* write message type */
|
||||
|
||||
writeChar(&ptr, gatewayid);
|
||||
writeInt(&ptr, duration);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into searchgw data
|
||||
* @param radius the returned broadcast radius of this message
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_searchgw(unsigned char* radius, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_SEARCHGW)
|
||||
goto exit;
|
||||
|
||||
*radius = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied gwinfo data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param gatewayid the gateway id
|
||||
* @param gatewayaddress_len the optional length of the gateway address (0 if none)
|
||||
* @param gatewayaddress the optional gateway address (NULL if none)
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_gwinfo(unsigned char* buf, int buflen, unsigned char gatewayid, unsigned short gatewayaddress_len,
|
||||
unsigned char* gatewayaddress)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(2 + gatewayaddress_len)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_GWINFO); /* write message type */
|
||||
|
||||
writeChar(&ptr, gatewayid);
|
||||
if (gatewayaddress_len > 0 && gatewayaddress != NULL)
|
||||
{
|
||||
memcpy(ptr, gatewayaddress, gatewayaddress_len);
|
||||
ptr += gatewayaddress_len;
|
||||
}
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
290
MQTTSNPacket/src/MQTTSNSerializePublish.c
Normal file
290
MQTTSNPacket/src/MQTTSNSerializePublish.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT publish packet that would be produced using the supplied parameters
|
||||
* @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
|
||||
* @param topicName the topic name to be used in the publish
|
||||
* @param payloadlen the length of the payload to be sent
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_publishLength(int payloadlen, MQTTSN_topicid topic, int qos)
|
||||
{
|
||||
int len = 6;
|
||||
|
||||
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
|
||||
len += topic.data.long_.len;
|
||||
|
||||
return payloadlen + len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied publish data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param qos integer - the MQTT QoS value
|
||||
* @param retained integer - the MQTT retained flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param topic MQTTSN_topicid - the MQTT topic in the publish
|
||||
* @param payload byte buffer - the MQTT publish payload
|
||||
* @param payloadlen integer - the length of the MQTT payload
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
|
||||
MQTTSN_topicid topic, unsigned char* payload, int payloadlen)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_publishLength(payloadlen, topic, qos))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_PUBLISH); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.dup = dup;
|
||||
flags.bits.QoS = qos;
|
||||
flags.bits.retain = retained;
|
||||
flags.bits.topicIdType = topic.type;
|
||||
writeChar(&ptr, flags.all);
|
||||
|
||||
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
|
||||
{
|
||||
/* special arrangement for long topic names in QoS -1 publishes. The length of the topic is in the topicid field */
|
||||
writeInt(&ptr, topic.data.long_.len); /* topic length */
|
||||
}
|
||||
else if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL || topic.type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
writeInt(&ptr, topic.data.id);
|
||||
else
|
||||
{
|
||||
writeChar(&ptr, topic.data.short_name[0]);
|
||||
writeChar(&ptr, topic.data.short_name[1]);
|
||||
}
|
||||
writeInt(&ptr, packetid);
|
||||
if (topic.type == MQTTSN_TOPIC_TYPE_NORMAL && qos == 3)
|
||||
{
|
||||
memcpy(ptr, topic.data.long_.name, topic.data.long_.len);
|
||||
ptr += topic.data.long_.len;
|
||||
}
|
||||
memcpy(ptr, payload, payloadlen);
|
||||
ptr += payloadlen;
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int MQTTSNSerialize_puback(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char returncode)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(6)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_PUBACK); /* write message type */
|
||||
|
||||
writeInt(&ptr, topicid);
|
||||
writeInt(&ptr, packetid);
|
||||
writeChar(&ptr, returncode);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the ack 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
|
||||
* @param type the MQTT-SN packet type
|
||||
* @param packetid the MQTT-SN packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_ack(unsigned char* buf, int buflen, unsigned short packet_type, unsigned short packetid)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *ptr = buf;
|
||||
int len = 4; /* ack packet length */
|
||||
|
||||
FUNC_ENTRY;
|
||||
if (len > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, packet_type); /* write packet type */
|
||||
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a puback 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
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_pubrec(unsigned char* buf, int buflen, unsigned short packetid)
|
||||
{
|
||||
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBREC, packetid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a pubrel 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
|
||||
* @param dup integer - the MQTT dup flag
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_pubrel(unsigned char* buf, int buflen, unsigned short packetid)
|
||||
{
|
||||
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBREL, packetid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a pubrel 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
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @return serialized length, or error if 0
|
||||
*/
|
||||
int MQTTSNSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
|
||||
{
|
||||
return MQTTSNSerialize_ack(buf, buflen, MQTTSN_PUBCOMP, packetid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTT register packet that would be produced using the supplied parameters
|
||||
* @param topicnamelen the length of the topic name to be used in the register
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_registerLength(int topicnamelen)
|
||||
{
|
||||
return topicnamelen + 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the supplied register data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param topicname null-terminated topic name string
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_register(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
MQTTSNString* topicname)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
int topicnamelen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
topicnamelen = (topicname->cstring) ? strlen(topicname->cstring) : topicname->lenstring.len;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_registerLength(topicnamelen))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_REGISTER); /* write message type */
|
||||
|
||||
writeInt(&ptr, topicid);
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
memcpy(ptr, (topicname->cstring) ? topicname->cstring : topicname->lenstring.data, topicnamelen);
|
||||
ptr += topicnamelen;
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied register data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param topicid if sent by a gateway, contains the id for the topicname, otherwise 0
|
||||
* @param packetid integer - the MQTT packet identifier
|
||||
* @param return_code integer return code
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_regack(unsigned char* buf, int buflen, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char return_code)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(6)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_REGACK); /* write message type */
|
||||
|
||||
writeInt(&ptr, topicid);
|
||||
writeInt(&ptr, packetid);
|
||||
writeChar(&ptr, return_code);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
30
MQTTSNPacket/src/MQTTSNSubscribe.h
Normal file
30
MQTTSNPacket/src/MQTTSNSubscribe.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#if !defined(MQTTSNSUBSCRIBE_H_)
|
||||
#define MQTTSNSUBSCRIBE_H_
|
||||
|
||||
int MQTTSNSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned short packetid,
|
||||
MQTTSN_topicid* topicFilter);
|
||||
int MQTTSNDeserialize_subscribe(unsigned char* dup, int* qos, unsigned short* packetid,
|
||||
MQTTSN_topicid* topicFilter, unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_suback(unsigned char* buf, int buflen, int qos, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char returncode);
|
||||
int MQTTSNDeserialize_suback(int* qos, unsigned short* topicid, unsigned short* packetid,
|
||||
unsigned char* returncode, unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNSUBSCRIBE_H_ */
|
||||
140
MQTTSNPacket/src/MQTTSNSubscribeClient.c
Normal file
140
MQTTSNPacket/src/MQTTSNSubscribeClient.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTTSN subscribe packet that would be produced using the supplied parameters,
|
||||
* excluding length
|
||||
* @param topicName the topic name to be used in the publish
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_subscribeLength(MQTTSN_topicid* topicFilter)
|
||||
{
|
||||
int len = 4;
|
||||
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
|
||||
len += topicFilter->data.long_.len;
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
len += 2;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied subscribe data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param dup integer - the MQTT-SN dup flag
|
||||
* @param qos integer - the MQTT-SN QoS value
|
||||
* @param packetid integer - the MQTT-SN packet identifier
|
||||
* @param topic MQTTSN_topicid - the MQTT-SN topic in the subscribe
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned short packetid,
|
||||
MQTTSN_topicid* topicFilter)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_subscribeLength(topicFilter))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_SUBSCRIBE); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.dup = dup;
|
||||
flags.bits.QoS = qos;
|
||||
flags.bits.topicIdType = topicFilter->type;
|
||||
writeChar(&ptr, flags.all);
|
||||
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
/* now the topic id or name */
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) /* means long topic name */
|
||||
{
|
||||
memcpy(ptr, topicFilter->data.long_.name, topicFilter->data.long_.len);
|
||||
ptr += topicFilter->data.long_.len;
|
||||
}
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
writeInt(&ptr, topicFilter->data.id);
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
|
||||
{
|
||||
writeChar(&ptr, topicFilter->data.short_name[0]);
|
||||
writeChar(&ptr, topicFilter->data.short_name[1]);
|
||||
}
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into suback data
|
||||
* @param qos the returned qos
|
||||
* @param topicid returned if "accepted" the value which will be used by the gateway in subsequent PUBLISH packets
|
||||
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
|
||||
* @param returncode returned - "accepted" or rejection reason
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_suback(int* qos, unsigned short* topicid, unsigned short* packetid,
|
||||
unsigned char* returncode, unsigned char* buf, int buflen)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_SUBACK)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*qos = flags.bits.QoS;
|
||||
|
||||
*topicid = readInt(&curdata);
|
||||
*packetid = readInt(&curdata);
|
||||
*returncode = readChar(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
119
MQTTSNPacket/src/MQTTSNSubscribeServer.c
Normal file
119
MQTTSNPacket/src/MQTTSNSubscribeServer.c
Normal file
@@ -0,0 +1,119 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
#include "MQTTSNPacket.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into subscribe data
|
||||
* @param dup the returned MQTT-SN dup flag
|
||||
* @param qos the returned qos
|
||||
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
|
||||
* @param topicFilter returned - the topic filter - normal, predefined or short
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_subscribe(unsigned char* dup, int* qos, unsigned short* packetid,
|
||||
MQTTSN_topicid* topicFilter, unsigned char* buf, int buflen)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_SUBSCRIBE)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*dup = flags.bits.dup;
|
||||
*qos = flags.bits.QoS;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
topicFilter->type = flags.bits.topicIdType;
|
||||
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
|
||||
{
|
||||
topicFilter->data.long_.len = enddata - curdata;
|
||||
topicFilter->data.long_.name = (char*)curdata;
|
||||
}
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
topicFilter->data.id = readInt(&curdata);
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
|
||||
{
|
||||
topicFilter->data.short_name[0] = readChar(&curdata);
|
||||
topicFilter->data.short_name[1] = readChar(&curdata);
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializes the supplied suback data into the supplied buffer, ready for sending
|
||||
* @param buf the buffer into which the packet will be serialized
|
||||
* @param buflen the length in bytes of the supplied buffer
|
||||
* @param qos integer - the MQTT-SN QoS value
|
||||
* @param topicid if "accepted" the value which will be used by the gateway in subsequent PUBLISH packets
|
||||
* @param packetid integer - the MQTT-SN packet identifier
|
||||
* @param returncode returned - "accepted" or rejection reason
|
||||
* @return the length of the serialized data. <= 0 indicates error
|
||||
*/
|
||||
int MQTTSNSerialize_suback(unsigned char* buf, int buflen, int qos, unsigned short topicid, unsigned short packetid,
|
||||
unsigned char returncode)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(7)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_SUBACK); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.QoS = qos;
|
||||
writeChar(&ptr, flags.all);
|
||||
|
||||
writeInt(&ptr, topicid);
|
||||
writeInt(&ptr, packetid);
|
||||
writeChar(&ptr, returncode);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
28
MQTTSNPacket/src/MQTTSNUnsubscribe.h
Normal file
28
MQTTSNPacket/src/MQTTSNUnsubscribe.h
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
|
||||
*******************************************************************************/
|
||||
|
||||
#if !defined(MQTTSNUNSUBSCRIBE_H_)
|
||||
#define MQTTSNUNSUBSCRIBE_H_
|
||||
|
||||
int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen,
|
||||
unsigned short packetid, MQTTSN_topicid* topicFilter);
|
||||
int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter,
|
||||
unsigned char* buf, int buflen);
|
||||
|
||||
int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
|
||||
int MQTTSNDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen);
|
||||
|
||||
#endif /* MQTTSNUNSUBSCRIBE_H_ */
|
||||
117
MQTTSNPacket/src/MQTTSNUnsubscribeClient.c
Normal file
117
MQTTSNPacket/src/MQTTSNUnsubscribeClient.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Determines the length of the MQTTSN subscribe packet that would be produced using the supplied parameters,
|
||||
* excluding length
|
||||
* @param topicName the topic name to be used in the publish
|
||||
* @return the length of buffer needed to contain the serialized version of the packet
|
||||
*/
|
||||
int MQTTSNSerialize_unsubscribeLength(MQTTSN_topicid* topicFilter)
|
||||
{
|
||||
int len = 4;
|
||||
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
|
||||
len += topicFilter->data.long_.len;
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT || topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
len += 2;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int MQTTSNSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned short packetid, MQTTSN_topicid* topicFilter)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
MQTTSNFlags flags;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(MQTTSNSerialize_unsubscribeLength(topicFilter))) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_UNSUBSCRIBE); /* write message type */
|
||||
|
||||
flags.all = 0;
|
||||
flags.bits.topicIdType = topicFilter->type;
|
||||
writeChar(&ptr, flags.all);
|
||||
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
/* now the topic id or name */
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL) /* means long topic name */
|
||||
{
|
||||
memcpy(ptr, topicFilter->data.long_.name, topicFilter->data.long_.len);
|
||||
ptr += topicFilter->data.long_.len;
|
||||
}
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
writeInt(&ptr, topicFilter->data.id);
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
|
||||
{
|
||||
writeChar(&ptr, topicFilter->data.short_name[0]);
|
||||
writeChar(&ptr, topicFilter->data.short_name[1]);
|
||||
}
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deserializes the supplied (wire) buffer into unsuback data
|
||||
* @param packetid returned - the same value as the one contained in the corresponding SUBSCRIBE
|
||||
* @param buf the raw buffer data, of the correct length determined by the remaining length field
|
||||
* @param buflen the length in bytes of the data in the supplied buffer
|
||||
* @return error code. 1 is success
|
||||
*/
|
||||
int MQTTSNDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
|
||||
{
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_UNSUBACK)
|
||||
goto exit;
|
||||
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
85
MQTTSNPacket/src/MQTTSNUnsubscribeServer.c
Normal file
85
MQTTSNPacket/src/MQTTSNUnsubscribeServer.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*******************************************************************************
|
||||
* 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 "StackTrace.h"
|
||||
#include "MQTTSNPacket.h"
|
||||
|
||||
int MQTTSNDeserialize_unsubscribe(unsigned short* packetid, MQTTSN_topicid* topicFilter,
|
||||
unsigned char* buf, int buflen)
|
||||
{
|
||||
MQTTSNFlags flags;
|
||||
unsigned char* curdata = buf;
|
||||
unsigned char* enddata = NULL;
|
||||
int rc = 0;
|
||||
int mylen = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
curdata += (rc = MQTTSNPacket_decode(curdata, buflen, &mylen)); /* read length */
|
||||
enddata = buf + mylen;
|
||||
if (enddata - curdata > buflen)
|
||||
goto exit;
|
||||
|
||||
if (readChar(&curdata) != MQTTSN_UNSUBSCRIBE)
|
||||
goto exit;
|
||||
|
||||
flags.all = readChar(&curdata);
|
||||
*packetid = readInt(&curdata);
|
||||
|
||||
topicFilter->type = flags.bits.topicIdType;
|
||||
if (topicFilter->type == MQTTSN_TOPIC_TYPE_NORMAL)
|
||||
{
|
||||
topicFilter->data.long_.len = enddata - curdata;
|
||||
topicFilter->data.long_.name = (char*)curdata;
|
||||
}
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_PREDEFINED)
|
||||
topicFilter->data.id = readInt(&curdata);
|
||||
else if (topicFilter->type == MQTTSN_TOPIC_TYPE_SHORT)
|
||||
{
|
||||
topicFilter->data.short_name[0] = readChar(&curdata);
|
||||
topicFilter->data.short_name[1] = readChar(&curdata);
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int MQTTSNSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
|
||||
{
|
||||
unsigned char *ptr = buf;
|
||||
int len = 0;
|
||||
int rc = 0;
|
||||
|
||||
FUNC_ENTRY;
|
||||
if ((len = MQTTSNPacket_len(7)) > buflen)
|
||||
{
|
||||
rc = MQTTSNPACKET_BUFFER_TOO_SHORT;
|
||||
goto exit;
|
||||
}
|
||||
ptr += MQTTSNPacket_encode(ptr, len); /* write length */
|
||||
writeChar(&ptr, MQTTSN_UNSUBACK); /* write message type */
|
||||
|
||||
writeInt(&ptr, packetid);
|
||||
|
||||
rc = ptr - buf;
|
||||
exit:
|
||||
FUNC_EXIT_RC(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
71
MQTTSNPacket/src/StackTrace.h
Normal file
71
MQTTSNPacket/src/StackTrace.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef STACKTRACE_H_
|
||||
#define STACKTRACE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#define NOSTACKTRACE 1
|
||||
|
||||
#if defined(NOSTACKTRACE)
|
||||
#define FUNC_ENTRY
|
||||
#define FUNC_ENTRY_NOLOG
|
||||
#define FUNC_ENTRY_MED
|
||||
#define FUNC_ENTRY_MAX
|
||||
#define FUNC_EXIT
|
||||
#define FUNC_EXIT_NOLOG
|
||||
#define FUNC_EXIT_MED
|
||||
#define FUNC_EXIT_MAX
|
||||
#define FUNC_EXIT_RC(x)
|
||||
#define FUNC_EXIT_MED_RC(x)
|
||||
#define FUNC_EXIT_MAX_RC(x)
|
||||
#else
|
||||
#if defined(WIN32)
|
||||
#define inline __inline
|
||||
#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
|
||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
|
||||
#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
|
||||
#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
|
||||
#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
|
||||
#else
|
||||
#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
|
||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
|
||||
#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
|
||||
#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
|
||||
#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
|
||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
|
||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
|
||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void StackTrace_entry(const char* name, int line, int trace);
|
||||
void StackTrace_exit(const char* name, int line, void* return_value, int trace);
|
||||
|
||||
void StackTrace_printStack(FILE* dest);
|
||||
char* StackTrace_get(unsigned long);
|
||||
|
||||
|
||||
#endif /* STACKTRACE_H_ */
|
||||
3
MQTTSNPacket/test/build_test
Normal file
3
MQTTSNPacket/test/build_test
Normal file
@@ -0,0 +1,3 @@
|
||||
gcc -Wall test1.c -o test1 -I../src ../src/MQTTSNConnectClient.c ../src/MQTTSNConnectServer.c ../src/MQTTSNPacket.c ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNSubscribeClient.c ../src/MQTTSNSubscribeServer.c ../src/MQTTSNUnsubscribeClient.c ../src/MQTTSNUnsubscribeServer.c ../src/MQTTSNSearchClient.c ../src/MQTTSNSearchServer.c
|
||||
|
||||
gcc -Wall test2.c -o test2 -I../src ../src/MQTTSNConnectClient.c ../src/MQTTSNConnectServer.c ../src/MQTTSNPacket.c ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNSubscribeClient.c
|
||||
956
MQTTSNPacket/test/test1.c
Normal file
956
MQTTSNPacket/test/test1.c
Normal file
@@ -0,0 +1,956 @@
|
||||
/*******************************************************************************
|
||||
* 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(_WINDOWS)
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#define EAGAIN WSAEWOULDBLOCK
|
||||
#define EINTR WSAEINTR
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define ENOTCONN WSAENOTCONN
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
struct Options
|
||||
{
|
||||
char* connection; /**< connection to system under test. */
|
||||
char** haconnections;
|
||||
int hacount;
|
||||
int verbose;
|
||||
int test_no;
|
||||
} options =
|
||||
{
|
||||
"tcp://m2m.eclipse.org:1883",
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
void usage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void getopts(int argc, char** argv)
|
||||
{
|
||||
int count = 1;
|
||||
|
||||
while (count < argc)
|
||||
{
|
||||
if (strcmp(argv[count], "--test_no") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
options.test_no = atoi(argv[count]);
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--connection") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
{
|
||||
options.connection = argv[count];
|
||||
printf("\nSetting connection to %s\n", options.connection);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--haconnections") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
{
|
||||
char* tok = strtok(argv[count], " ");
|
||||
options.hacount = 0;
|
||||
options.haconnections = malloc(sizeof(char*) * 5);
|
||||
while (tok)
|
||||
{
|
||||
options.haconnections[options.hacount] = malloc(strlen(tok) + 1);
|
||||
strcpy(options.haconnections[options.hacount], tok);
|
||||
options.hacount++;
|
||||
tok = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--verbose") == 0)
|
||||
{
|
||||
options.verbose = 1;
|
||||
printf("\nSetting verbose on\n");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define LOGA_DEBUG 0
|
||||
#define LOGA_INFO 1
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/timeb.h>
|
||||
void MyLog(int LOGA_level, char* format, ...)
|
||||
{
|
||||
static char msg_buf[256];
|
||||
va_list args;
|
||||
struct timeb ts;
|
||||
|
||||
struct tm *timeinfo;
|
||||
|
||||
if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
|
||||
return;
|
||||
|
||||
ftime(&ts);
|
||||
timeinfo = localtime(&ts.time);
|
||||
strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
|
||||
|
||||
sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s\n", msg_buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32) || defined(_WINDOWS)
|
||||
#define mqsleep(A) Sleep(1000*A)
|
||||
#define START_TIME_TYPE DWORD
|
||||
static DWORD start_time = 0;
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
#elif defined(AIX)
|
||||
#define mqsleep sleep
|
||||
#define START_TIME_TYPE struct timespec
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
static struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
return start;
|
||||
}
|
||||
#else
|
||||
#define mqsleep sleep
|
||||
#define START_TIME_TYPE struct timeval
|
||||
/* TODO - unused - remove? static struct timeval start_time; */
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
struct timeval start_time;
|
||||
gettimeofday(&start_time, NULL);
|
||||
return start_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
long elapsed(START_TIME_TYPE start_time)
|
||||
{
|
||||
return GetTickCount() - start_time;
|
||||
}
|
||||
#elif defined(AIX)
|
||||
#define assert(a)
|
||||
long elapsed(struct timespec start)
|
||||
{
|
||||
struct timespec now, res;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
ntimersub(now, start, res);
|
||||
return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
|
||||
}
|
||||
#else
|
||||
long elapsed(START_TIME_TYPE start_time)
|
||||
{
|
||||
struct timeval now, res;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&now, &start_time, &res);
|
||||
return (res.tv_sec)*1000 + (res.tv_usec)/1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
|
||||
#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
|
||||
|
||||
int tests = 0;
|
||||
int failures = 0;
|
||||
FILE* xml;
|
||||
START_TIME_TYPE global_start_time;
|
||||
char output[3000];
|
||||
char* cur_output = output;
|
||||
|
||||
|
||||
void write_test_result()
|
||||
{
|
||||
long duration = elapsed(global_start_time);
|
||||
|
||||
fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
|
||||
if (cur_output != output)
|
||||
{
|
||||
fprintf(xml, "%s", output);
|
||||
cur_output = output;
|
||||
}
|
||||
fprintf(xml, "</testcase>\n");
|
||||
}
|
||||
|
||||
|
||||
void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
|
||||
{
|
||||
++tests;
|
||||
if (!value)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
++failures;
|
||||
printf("Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
|
||||
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
|
||||
description, filename, lineno);
|
||||
}
|
||||
else
|
||||
MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
|
||||
}
|
||||
|
||||
#define min(a, b) ((a < b) ? a : b)
|
||||
|
||||
int checkMQTTSNStrings(MQTTSNString a, MQTTSNString b)
|
||||
{
|
||||
if (!a.lenstring.data)
|
||||
{
|
||||
a.lenstring.data = a.cstring;
|
||||
if (a.cstring)
|
||||
a.lenstring.len = strlen(a.cstring);
|
||||
}
|
||||
if (!b.lenstring.data)
|
||||
{
|
||||
b.lenstring.data = b.cstring;
|
||||
if (b.cstring)
|
||||
b.lenstring.len = strlen(b.cstring);
|
||||
}
|
||||
return memcmp(a.lenstring.data, b.lenstring.data, min(a.lenstring.len, b.lenstring.len)) == 0;
|
||||
}
|
||||
|
||||
int checkMQTTSNTopics(MQTTSN_topicid a, MQTTSN_topicid b)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (a.type != b.type)
|
||||
goto exit;
|
||||
|
||||
if (a.data.long_.name)
|
||||
rc = memcmp(a.data.long_.name, b.data.long_.name, a.data.long_.len) == 0;
|
||||
else if (a.type == MQTTSN_TOPIC_TYPE_SHORT)
|
||||
rc = (memcpy(a.data.short_name, b.data.short_name, 2) == 0);
|
||||
else
|
||||
rc = (a.data.id == b.data.id);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int checkConnectPackets(MQTTSNPacket_connectData* before, MQTTSNPacket_connectData* after)
|
||||
{
|
||||
int rc = 0;
|
||||
int start_failures = failures;
|
||||
|
||||
assert("struct_ids should be the same",
|
||||
memcmp(before->struct_id, after->struct_id, 4) == 0, "struct_ids were different %.4s\n", after->struct_id);
|
||||
|
||||
assert("struct_versions should be the same",
|
||||
before->struct_version == after->struct_version, "struct_versions were different\n", rc);
|
||||
|
||||
assert("ClientIDs should be the same",
|
||||
checkMQTTSNStrings(before->clientID, after->clientID), "ClientIDs were different\n", rc);
|
||||
|
||||
assert("durations should be the same",
|
||||
before->duration == after->duration, "durations were different\n", rc);
|
||||
|
||||
assert("cleansessions should be the same",
|
||||
before->cleansession == after->cleansession, "cleansessions were different\n", rc);
|
||||
|
||||
assert("willFlags should be the same",
|
||||
before->willFlag == after->willFlag, "willFlags were different\n", rc);
|
||||
|
||||
return failures == start_failures;
|
||||
}
|
||||
|
||||
int test1(struct Options options)
|
||||
{
|
||||
MQTTSNPacket_connectData data = MQTTSNPacket_connectData_initializer;
|
||||
MQTTSNPacket_connectData data_after = MQTTSNPacket_connectData_initializer;
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
MQTTSNString clientid = MQTTSNString_initializer, clientid_after = MQTTSNString_initializer;
|
||||
int duration_after = -1;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 1 - serialization of connect and back");
|
||||
|
||||
data.clientID.cstring = "me too";
|
||||
|
||||
data.duration = 20;
|
||||
data.cleansession = 1;
|
||||
|
||||
data.willFlag = 1;
|
||||
|
||||
rc = MQTTSNSerialize_connect(buf, buflen, &data);
|
||||
assert("good rc from serialize connect", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_connect(&data_after, buf, buflen);
|
||||
assert("good rc from deserialize connect", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
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",
|
||||
checkMQTTSNStrings(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",
|
||||
checkMQTTSNStrings(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);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test2(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
|
||||
unsigned char dup = 0;
|
||||
int qos = 2;
|
||||
unsigned char retained = 0;
|
||||
unsigned short msgid = 23;
|
||||
MQTTSN_topicid topic;
|
||||
unsigned char *payload = (unsigned char*)"kkhkhkjkj jkjjk jk jk ";
|
||||
int payloadlen = strlen((char*)payload);
|
||||
|
||||
unsigned char dup2 = 1;
|
||||
int qos2 = 1;
|
||||
unsigned char retained2 = 1;
|
||||
unsigned short msgid2 = 3243;
|
||||
MQTTSN_topicid topic2;
|
||||
unsigned char *payload2 = NULL;
|
||||
int payloadlen2 = 0;
|
||||
unsigned char acktype;
|
||||
|
||||
unsigned char returncode = 3, returncode2 = -99;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 2 - serialization of publish and back");
|
||||
|
||||
memset(&topic, 0, sizeof(topic));
|
||||
memset(&topic2, 0, sizeof(topic2));
|
||||
topic.type = MQTTSN_TOPIC_TYPE_SHORT;
|
||||
memcpy(topic.data.short_name, "my", 2);
|
||||
rc = MQTTSNSerialize_publish(buf, buflen, dup, qos, retained, msgid, topic,
|
||||
payload, payloadlen);
|
||||
assert("good rc from serialize publish", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_publish(&dup2, &qos2, &retained2, &msgid2, &topic2,
|
||||
&payload2, &payloadlen2, buf, buflen);
|
||||
assert("good rc from deserialize publish", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
|
||||
assert("qoss should be the same", qos == qos2, "qoss were different %d\n", qos2);
|
||||
assert("retaineds should be the same", retained == retained2, "retaineds were different %d\n", retained2);
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
|
||||
assert("topics should be the same",
|
||||
checkMQTTSNTopics(topic, topic2), "topics were different %s\n", "");
|
||||
|
||||
assert("payload lengths should be the same",
|
||||
payloadlen == payloadlen2, "payload lengths were different %d\n", payloadlen2);
|
||||
|
||||
assert("payloads should be the same",
|
||||
memcmp(payload, payload2, payloadlen) == 0, "payloads were different %s\n", "");
|
||||
|
||||
rc = MQTTSNSerialize_puback(buf, buflen, topic.data.id, msgid, returncode);
|
||||
assert("good rc from serialize puback", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_puback(&topic2.data.id, &msgid2, &returncode2, buf, buflen);
|
||||
assert("good rc from deserialize puback", rc > 0, "rc was %d\n", rc);
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
assert("return codes should be the same", returncode == returncode2, "return codes were different %d\n", returncode2);
|
||||
|
||||
rc = MQTTSNSerialize_pubrec(buf, buflen, msgid);
|
||||
assert("good rc from serialize pubrec", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_ack(&acktype, &msgid2, buf, buflen);
|
||||
assert("good rc from deserialize pubrec", rc == 1, "rc was %d\n", rc);
|
||||
assert("Acktype should be MQTTSN_PUBREC", acktype == MQTTSN_PUBREC, "acktype was %d\n", acktype);
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
|
||||
/*exit:*/
|
||||
MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
int willQoS = 1, willQoS1 = 0;
|
||||
unsigned char willRetain = 1, willRetain1 = 0;
|
||||
MQTTSNString willTopic = MQTTSNString_initializer, willTopic1 = MQTTSNString_initializer;
|
||||
willTopic.cstring = "a will topic";
|
||||
rc = MQTTSNSerialize_willtopic(buf, buflen, willQoS, willRetain, willTopic);
|
||||
assert("good rc from serialize willtopic", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willtopic(&willQoS1, &willRetain1, &willTopic1, buf, rc);
|
||||
assert("good rc from deserialize willtopic", rc == 1, "rc was %d\n", rc);
|
||||
assert("willQoSs are the same", willQoS == willQoS1, "willQoS1 was %d\n", willQoS1);
|
||||
assert("willRetains are the same", willRetain == willRetain1, "willRetain1 was %d\n", willRetain1);
|
||||
assert("willTopics are the same", checkMQTTSNStrings(willTopic, willTopic1), "willTopic1 was %.s\n", willTopic1.lenstring.data);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
willQoS = 2; willRetain = 1; willQoS1 = 0; willRetain1 = 0;
|
||||
MQTTSNString initTopic = MQTTSNString_initializer;
|
||||
memcpy(&willTopic, &initTopic, sizeof(initTopic));
|
||||
memcpy(&willTopic1, &initTopic, sizeof(initTopic));
|
||||
willTopic.cstring = "a will topic update";
|
||||
rc = MQTTSNSerialize_willtopicupd(buf, buflen, willQoS, willRetain, willTopic);
|
||||
assert("good rc from serialize willtopicupd", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willtopicupd(&willQoS1, &willRetain1, &willTopic1, buf, rc);
|
||||
assert("good rc from deserialize willtopicupd", rc == 1, "rc was %d\n", rc);
|
||||
assert("willQoSs are the same", willQoS == willQoS1, "willQoS1 was %d\n", willQoS1);
|
||||
assert("willRetains are the same", willRetain == willRetain1, "willRetain1 was %d\n", willRetain1);
|
||||
assert("willTopics are the same", checkMQTTSNStrings(willTopic, willTopic1), "willTopic1 was %.s\n", willTopic1.lenstring.data);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
MQTTSNString willMsg = MQTTSNString_initializer, willMsg1 = MQTTSNString_initializer;
|
||||
willMsg.cstring = "a will message";
|
||||
rc = MQTTSNSerialize_willmsg(buf, buflen, willMsg);
|
||||
assert("good rc from serialize willmsg", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willmsg(&willMsg1, buf, rc);
|
||||
assert("good rc from deserialize willmsg", rc == 1, "rc was %d\n", rc);
|
||||
assert("willMsgs are the same", checkMQTTSNStrings(willMsg, willMsg1), "willMsg1 was %.s\n", willMsg1.lenstring.data);
|
||||
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
memcpy(&willMsg, &initTopic, sizeof(initTopic));
|
||||
memcpy(&willMsg1, &initTopic, sizeof(initTopic));
|
||||
willMsg.cstring = "a will message";
|
||||
rc = MQTTSNSerialize_willmsgupd(buf, buflen, willMsg);
|
||||
assert("good rc from serialize willmsgupd", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willmsgupd(&willMsg1, buf, rc);
|
||||
assert("good rc from deserialize willmsgupd", rc == 1, "rc was %d\n", rc);
|
||||
assert("willMsgs are the same", checkMQTTSNStrings(willMsg, willMsg1), "willMsg1 was %.s\n", willMsg1.lenstring.data);
|
||||
|
||||
int resp_rc = 33, resp_rc2 = 0;
|
||||
rc = MQTTSNSerialize_willmsgresp(buf, buflen, resp_rc);
|
||||
assert("good rc from serialize willmsgresp", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willmsgresp(&resp_rc2, buf, buflen);
|
||||
assert("good rc from deserialize willmsgresp", rc == 1, "rc was %d\n", rc);
|
||||
assert("resp rcs should be the same", resp_rc == resp_rc2, "resp rcs were different %d\n", resp_rc2);
|
||||
|
||||
resp_rc = 67, resp_rc2 = 0;
|
||||
rc = MQTTSNSerialize_willtopicresp(buf, buflen, resp_rc);
|
||||
assert("good rc from serialize willmsgresp", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_willtopicresp(&resp_rc2, buf, buflen);
|
||||
assert("good rc from deserialize willmsgresp", rc == 1, "rc was %d\n", rc);
|
||||
assert("resp rcs should be the same", resp_rc == resp_rc2, "resp rcs were different %d\n", resp_rc2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST3: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int test4(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
size_t buflen = sizeof(buf);
|
||||
|
||||
unsigned char dup = 0;
|
||||
unsigned short packetid = 23;
|
||||
MQTTSN_topicid topicFilter;
|
||||
int req_qos = 2;
|
||||
|
||||
unsigned char dup2 = 1;
|
||||
unsigned short packetid2 = 2223;
|
||||
MQTTSN_topicid topicFilter2;
|
||||
int req_qos2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test4\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 4 - serialization of subscribe and back");
|
||||
|
||||
memset(&topicFilter, '\0', sizeof(topicFilter));
|
||||
memset(&topicFilter2, '\0', sizeof(topicFilter2));
|
||||
topicFilter.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topicFilter.data.long_.name = "mytopic";
|
||||
topicFilter.data.long_.len = strlen(topicFilter.data.long_.name);
|
||||
rc = MQTTSNSerialize_subscribe(buf, buflen, dup, req_qos, packetid, &topicFilter);
|
||||
assert("good rc from serialize subscribe", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_subscribe(&dup2, &req_qos2, &packetid2, &topicFilter2, buf, buflen);
|
||||
assert("good rc from deserialize subscribe", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
|
||||
assert("msgids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
|
||||
assert("topics should be the same",
|
||||
checkMQTTSNTopics(topicFilter, topicFilter2), "topics were different %s\n", "");
|
||||
assert("qoss should be the same", req_qos == req_qos2, "qoss were different %d\n", req_qos2);
|
||||
|
||||
/*exit:*/
|
||||
MyLog(LOGA_INFO, "TEST4: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test5(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
size_t buflen = sizeof(buf);
|
||||
|
||||
unsigned short packetid = 23;
|
||||
MQTTSN_topicid topicFilter;
|
||||
|
||||
unsigned short packetid2 = 2223;
|
||||
MQTTSN_topicid topicFilter2;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test5\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 5 - serialization of unsubscribe and back");
|
||||
|
||||
memset(&topicFilter, '\0', sizeof(topicFilter));
|
||||
memset(&topicFilter2, '\0', sizeof(topicFilter2));
|
||||
topicFilter.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topicFilter.data.long_.name = "mytopic";
|
||||
topicFilter.data.long_.len = strlen(topicFilter.data.long_.name);
|
||||
rc = MQTTSNSerialize_unsubscribe(buf, buflen, packetid, &topicFilter);
|
||||
assert("good rc from serialize unsubscribe", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_unsubscribe(&packetid2, &topicFilter2, buf, buflen);
|
||||
assert("good rc from deserialize unsubscribe", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("msgids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
|
||||
assert("topics should be the same",
|
||||
checkMQTTSNTopics(topicFilter, topicFilter2), "topics were different %s\n", "");
|
||||
|
||||
/*exit:*/
|
||||
MyLog(LOGA_INFO, "TEST5: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test6(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
|
||||
int connack_rc = 77;
|
||||
|
||||
int connack_rc2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test6\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 6 - serialization of connack and back");
|
||||
|
||||
rc = MQTTSNSerialize_connack(buf, buflen, connack_rc);
|
||||
assert("good rc from serialize connack", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_connack(&connack_rc2, buf, buflen);
|
||||
assert("good rc from deserialize connack", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("connack rcs should be the same", connack_rc == connack_rc2, "connack rcs were different %d\n", connack_rc2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST6: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test7(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned short packetid = 255, packetid2 = 0;
|
||||
int qos = 2, qos2 = 0;
|
||||
unsigned short topicid = 233, topicid2 = 0;
|
||||
unsigned char return_code = 32, return_code2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test7\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 7 - serialization of suback and back");
|
||||
|
||||
rc = MQTTSNSerialize_suback(buf, buflen, qos, topicid, packetid, return_code);
|
||||
assert("good rc from serialize suback", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_suback(&qos2, &topicid2, &packetid2, &return_code2, buf, buflen);
|
||||
assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
assert("qoss should be the same", qos == qos2, "qoss were different %d\n", qos2);
|
||||
assert("topicids should be the same", topicid == topicid2, "topicids were different %d\n", topicid2);
|
||||
assert("return codes should be the same", return_code == return_code2, "return codes were different %d\n", return_code2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST7: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test8(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned short packetid = 255, packetid2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test8\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 8 - serialization of unsuback and back");
|
||||
|
||||
rc = MQTTSNSerialize_unsuback(buf, buflen, packetid);
|
||||
assert("good rc from serialize unsuback", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_unsuback(&packetid2, buf, buflen);
|
||||
assert("good rc from deserialize unsuback", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST8: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test9(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned short packetid = 255, packetid2 = 0;
|
||||
unsigned short topicid = 233, topicid2 = 0;
|
||||
MQTTSNString topicname = MQTTSNString_initializer, topicname2 = MQTTSNString_initializer;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test9\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 9 - serialization of register and back");
|
||||
|
||||
rc = MQTTSNSerialize_register(buf, buflen, topicid, packetid, &topicname);
|
||||
assert("good rc from serialize register", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_register(&topicid2, &packetid2, &topicname2, buf, buflen);
|
||||
assert("good rc from deserialize register", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
assert("topicids should be the same", topicid == topicid2, "topicids were different %d\n", topicid2);
|
||||
assert("topicnames should be the same",
|
||||
checkMQTTSNStrings(topicname, topicname2), "topicnames were different\n", rc);
|
||||
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST9: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test10(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned short packetid = 255, packetid2 = 0;
|
||||
unsigned short topicid = 233, topicid2 = 0;
|
||||
unsigned char return_code = 127, return_code2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test10\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 10 - serialization of regack and back");
|
||||
|
||||
rc = MQTTSNSerialize_regack(buf, buflen, topicid, packetid, return_code);
|
||||
assert("good rc from serialize regack", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_regack(&topicid2, &packetid2, &return_code2, buf, buflen);
|
||||
assert("good rc from deserialize regack", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("packetids should be the same", packetid == packetid2, "packetids were different %d\n", packetid2);
|
||||
assert("topicids should be the same", topicid == topicid2, "topicids were different %d\n", topicid2);
|
||||
assert("return codes should be the same", return_code == return_code2, "return_codes were different %d\n", return_code2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST10: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test11(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned char gatewayid = 255, gatewayid2 = 0;
|
||||
unsigned short duration = 3233, duration2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test11\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 11 - serialization of advertise and back");
|
||||
|
||||
rc = MQTTSNSerialize_advertise(buf, buflen, gatewayid, duration);
|
||||
assert("good rc from serialize advertise", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_advertise(&gatewayid2, &duration2, buf, buflen);
|
||||
assert("good rc from deserialize advertise", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("gatewayids should be the same", gatewayid == gatewayid2, "gatewayids were different %d\n", gatewayid2);
|
||||
assert("return codes should be the same", duration == duration2, "return_codes were different %d\n", duration2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST11: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test12(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned char radius = 255, radius2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test12\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 12 - serialization of searchgw and back");
|
||||
|
||||
rc = MQTTSNSerialize_searchgw(buf, buflen, radius);
|
||||
assert("good rc from serialize searchgw", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_searchgw(&radius2, buf, buflen);
|
||||
assert("good rc from deserialize searchgw", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("radiuss should be the same", radius == radius2, "radiuss were different %d\n", radius2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST12: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test13(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
unsigned char gatewayid = 255, gatewayid2 = 0;
|
||||
unsigned short gatewayaddress_len = 16, gatewayaddress_len2 = 0;
|
||||
unsigned char gatewayaddress[40] = "a gateway address", *gatewayaddress2 = NULL;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test11\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 13 - serialization of gwinfo and back");
|
||||
|
||||
rc = MQTTSNSerialize_gwinfo(buf, buflen, gatewayid, gatewayaddress_len, gatewayaddress);
|
||||
assert("good rc from serialize gwinfo", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_gwinfo(&gatewayid2, &gatewayaddress_len2, &gatewayaddress2, buf, buflen);
|
||||
assert("good rc from deserialize gwinfo", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
assert("gatewayids should be the same", gatewayid == gatewayid2, "gatewayids were different %d\n", gatewayid2);
|
||||
assert("gateway lengths should be the same", gatewayaddress_len == gatewayaddress_len2, "gateway lengths were different %d\n", gatewayaddress_len2);
|
||||
assert("gateway addresses should be the same", memcmp(gatewayaddress, gatewayaddress2, gatewayaddress_len) == 0,
|
||||
"gateway addresses were different %.10s\n", gatewayaddress2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST13: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11, test12, test13};
|
||||
|
||||
xml = fopen("TEST-test1.xml", "w");
|
||||
fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
|
||||
|
||||
getopts(argc, argv);
|
||||
|
||||
if (options.test_no == 0)
|
||||
{ /* run all the tests */
|
||||
for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
|
||||
rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */
|
||||
}
|
||||
else
|
||||
rc = tests[options.test_no](options); /* run just the selected test */
|
||||
|
||||
if (rc == 0)
|
||||
MyLog(LOGA_INFO, "verdict pass");
|
||||
else
|
||||
MyLog(LOGA_INFO, "verdict fail");
|
||||
|
||||
fprintf(xml, "</testsuite>\n");
|
||||
fclose(xml);
|
||||
return rc;
|
||||
}
|
||||
703
MQTTSNPacket/test/test2.c
Normal file
703
MQTTSNPacket/test/test2.c
Normal file
@@ -0,0 +1,703 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(_WINDOWS)
|
||||
#define INVALID_SOCKET SOCKET_ERROR
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#define EAGAIN WSAEWOULDBLOCK
|
||||
#define EINTR WSAEINTR
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define ENOTCONN WSAENOTCONN
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#endif
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
struct Options
|
||||
{
|
||||
char* host;
|
||||
int port;
|
||||
int verbose;
|
||||
int test_no;
|
||||
} options =
|
||||
{
|
||||
"127.0.0.1",
|
||||
1884,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
void usage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void getopts(int argc, char** argv)
|
||||
{
|
||||
int count = 1;
|
||||
|
||||
while (count < argc)
|
||||
{
|
||||
if (strcmp(argv[count], "--test_no") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
options.test_no = atoi(argv[count]);
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--host") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
{
|
||||
options.host = argv[count];
|
||||
printf("\nSetting host to %s\n", options.host);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--port") == 0)
|
||||
{
|
||||
if (++count < argc)
|
||||
options.port = atoi(argv[count]);
|
||||
else
|
||||
usage();
|
||||
}
|
||||
else if (strcmp(argv[count], "--verbose") == 0)
|
||||
{
|
||||
options.verbose = 1;
|
||||
printf("\nSetting verbose on\n");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define LOGA_DEBUG 0
|
||||
#define LOGA_INFO 1
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/timeb.h>
|
||||
void MyLog(int LOGA_level, char* format, ...)
|
||||
{
|
||||
static char msg_buf[256];
|
||||
va_list args;
|
||||
struct timeb ts;
|
||||
|
||||
struct tm *timeinfo;
|
||||
|
||||
if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
|
||||
return;
|
||||
|
||||
ftime(&ts);
|
||||
timeinfo = localtime(&ts.time);
|
||||
strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
|
||||
|
||||
sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
|
||||
va_end(args);
|
||||
|
||||
printf("%s\n", msg_buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32) || defined(_WINDOWS)
|
||||
#define mqsleep(A) Sleep(1000*A)
|
||||
#define START_TIME_TYPE DWORD
|
||||
static DWORD start_time = 0;
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
#elif defined(AIX)
|
||||
#define mqsleep sleep
|
||||
#define START_TIME_TYPE struct timespec
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
static struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
return start;
|
||||
}
|
||||
#else
|
||||
#define mqsleep sleep
|
||||
#define START_TIME_TYPE struct timeval
|
||||
/* TODO - unused - remove? static struct timeval start_time; */
|
||||
START_TIME_TYPE start_clock(void)
|
||||
{
|
||||
struct timeval start_time;
|
||||
gettimeofday(&start_time, NULL);
|
||||
return start_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
long elapsed(START_TIME_TYPE start_time)
|
||||
{
|
||||
return GetTickCount() - start_time;
|
||||
}
|
||||
#elif defined(AIX)
|
||||
#define assert(a)
|
||||
long elapsed(struct timespec start)
|
||||
{
|
||||
struct timespec now, res;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
ntimersub(now, start, res);
|
||||
return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
|
||||
}
|
||||
#else
|
||||
long elapsed(START_TIME_TYPE start_time)
|
||||
{
|
||||
struct timeval now, res;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timersub(&now, &start_time, &res);
|
||||
return (res.tv_sec)*1000 + (res.tv_usec)/1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
|
||||
#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
|
||||
|
||||
int tests = 0;
|
||||
int failures = 0;
|
||||
FILE* xml;
|
||||
START_TIME_TYPE global_start_time;
|
||||
char output[3000];
|
||||
char* cur_output = output;
|
||||
|
||||
|
||||
void write_test_result()
|
||||
{
|
||||
long duration = elapsed(global_start_time);
|
||||
|
||||
fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
|
||||
if (cur_output != output)
|
||||
{
|
||||
fprintf(xml, "%s", output);
|
||||
cur_output = output;
|
||||
}
|
||||
fprintf(xml, "</testcase>\n");
|
||||
}
|
||||
|
||||
|
||||
void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
|
||||
{
|
||||
++tests;
|
||||
if (!value)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
++failures;
|
||||
printf("Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
|
||||
|
||||
va_start(args, format);
|
||||
vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
|
||||
description, filename, lineno);
|
||||
}
|
||||
else
|
||||
MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
|
||||
}
|
||||
|
||||
#define min(a, b) ((a < b) ? a : b)
|
||||
|
||||
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;
|
||||
|
||||
int getdata(unsigned char* buf, int count)
|
||||
{
|
||||
int rc = recvfrom(mysock, buf, count, 0, NULL, NULL);
|
||||
//printf("received %d bytes count %d\n", rc, (int)count);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int connectDisconnect(struct Options options)
|
||||
{
|
||||
MQTTSNPacket_connectData data = MQTTSNPacket_connectData_initializer;
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
int len = 0;
|
||||
|
||||
mysock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (mysock == INVALID_SOCKET)
|
||||
rc = Socket_error("socket", mysock);
|
||||
|
||||
data.clientID.cstring = "test2/test1";
|
||||
|
||||
data.cleansession = 0;
|
||||
|
||||
rc = MQTTSNSerialize_connect(buf, buflen, &data);
|
||||
assert("good rc from serialize connect", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = sendPacketBuffer(mysock, options.host, options.port, buf, rc);
|
||||
assert("good rc from sendPacketBuffer", rc == 0, "rc was %d\n", rc);
|
||||
|
||||
/* 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;
|
||||
|
||||
len = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
rc = sendPacketBuffer(mysock, options.host, options.port, buf, len);
|
||||
|
||||
rc = shutdown(mysock, SHUT_WR);
|
||||
rc = close(mysock);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int test1(struct Options options)
|
||||
{
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"reconnect\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 1 - reconnection");
|
||||
|
||||
connectDisconnect(options);
|
||||
connectDisconnect(options);
|
||||
|
||||
MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int connectSubscribeDisconnect(struct Options options)
|
||||
{
|
||||
MQTTSNPacket_connectData data = MQTTSNPacket_connectData_initializer;
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
int len = 0;
|
||||
MQTTSN_topicid topic;
|
||||
|
||||
mysock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (mysock == INVALID_SOCKET)
|
||||
rc = Socket_error("socket", mysock);
|
||||
|
||||
data.clientID.cstring = "test2/test1";
|
||||
|
||||
data.cleansession = 0;
|
||||
|
||||
rc = MQTTSNSerialize_connect(buf, buflen, &data);
|
||||
assert("good rc from serialize connect", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = sendPacketBuffer(mysock, options.host, options.port, buf, rc);
|
||||
assert("good rc from sendPacketBuffer", rc == 0, "rc was %d\n", rc);
|
||||
|
||||
/* wait for connack */
|
||||
if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_CONNACK)
|
||||
{
|
||||
int connack_rc = -1;
|
||||
|
||||
rc = MQTTSNDeserialize_connack(&connack_rc, buf, buflen);
|
||||
assert("Good rc from deserialize connack", rc == 1, "rc was %d\n", rc);
|
||||
assert("Good rc from connect", connack_rc == 0, "connack_rc was %d\n", rc);
|
||||
if (connack_rc != 0)
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
/* subscribe */
|
||||
printf("Subscribing\n");
|
||||
topic.type = MQTTSN_TOPIC_TYPE_NORMAL;
|
||||
topic.data.long_.name = "substopic";
|
||||
topic.data.long_.len = strlen(topic.data.long_.name);
|
||||
len = MQTTSNSerialize_subscribe(buf, buflen, 0, 2, /*msgid*/ 1, &topic);
|
||||
rc = sendPacketBuffer(mysock, options.host, options.port, buf, len);
|
||||
|
||||
if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_SUBACK) /* wait for suback */
|
||||
{
|
||||
unsigned short submsgid;
|
||||
int granted_qos;
|
||||
unsigned char returncode;
|
||||
unsigned short topicid;
|
||||
|
||||
rc = MQTTSNDeserialize_suback(&granted_qos, &topicid, &submsgid, &returncode, buf, buflen);
|
||||
if (granted_qos != 2 || returncode != 0)
|
||||
{
|
||||
printf("granted qos != 2, %d return code %d\n", granted_qos, returncode);
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
printf("suback topic id %d\n", topicid);
|
||||
}
|
||||
else
|
||||
goto exit;
|
||||
|
||||
len = MQTTSNSerialize_disconnect(buf, buflen, 0);
|
||||
rc = sendPacketBuffer(mysock, options.host, options.port, buf, len);
|
||||
|
||||
rc = shutdown(mysock, SHUT_WR);
|
||||
rc = close(mysock);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Connect non-cleansession, subscribe, disconnect.
|
||||
* Then reconnect non-cleansession.
|
||||
*/
|
||||
int test2(struct Options options)
|
||||
{
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test2\" name=\"clientid free\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 2 - clientid free");
|
||||
|
||||
connectSubscribeDisconnect(options);
|
||||
connectDisconnect(options);
|
||||
|
||||
MyLog(LOGA_INFO, "TEST2: 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
#define TOPIC_COUNT 2
|
||||
|
||||
int dup = 0;
|
||||
int msgid = 23;
|
||||
int count = TOPIC_COUNT;
|
||||
MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
|
||||
int req_qoss[TOPIC_COUNT] = {2, 1};
|
||||
|
||||
int dup2 = 1;
|
||||
int msgid2 = 2223;
|
||||
int count2 = 0;
|
||||
MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
|
||||
int req_qoss2[TOPIC_COUNT] = {0, 0};
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 2 - serialization of subscribe and back");
|
||||
|
||||
topicStrings[0].cstring = "mytopic";
|
||||
topicStrings[1].cstring = "mytopic2";
|
||||
rc = MQTTSerialize_subscribe(buf, buflen, dup, msgid, count, topicStrings, req_qoss);
|
||||
assert("good rc from serialize subscribe", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTDeserialize_subscribe(&dup2, &msgid2, 2, &count2, topicStrings2, req_qoss2, buf, buflen);
|
||||
assert("good rc from deserialize subscribe", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
|
||||
assert("count should be the same", count == count2, "counts were different %d\n", count2);
|
||||
|
||||
for (i = 0; i < count2; ++i)
|
||||
{
|
||||
assert("topics should be the same",
|
||||
checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
|
||||
|
||||
assert("qoss should be the same", req_qoss[i] == req_qoss2[i], "qoss were different %d\n", req_qoss2[i]);
|
||||
}
|
||||
|
||||
/*exit:*/
|
||||
MyLog(LOGA_INFO, "TEST3: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test4(struct Options options)
|
||||
{
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
#define TOPIC_COUNT 2
|
||||
|
||||
int msgid = 23;
|
||||
int count = TOPIC_COUNT;
|
||||
int granted_qoss[TOPIC_COUNT] = {2, 1};
|
||||
;
|
||||
int msgid2 = 2223;
|
||||
int count2 = 0;
|
||||
int granted_qoss2[TOPIC_COUNT] = {0, 0};
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 4 - serialization of suback and back");
|
||||
|
||||
rc = MQTTSerialize_suback(buf, buflen, msgid, count, granted_qoss);
|
||||
assert("good rc from serialize suback", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTDeserialize_suback(&msgid2, 2, &count2, granted_qoss2, buf, buflen);
|
||||
assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
|
||||
assert("count should be the same", count == count2, "counts were different %d\n", count2);
|
||||
|
||||
for (i = 0; i < count2; ++i)
|
||||
assert("qoss should be the same", granted_qoss[i] == granted_qoss2[i], "qoss were different %d\n", granted_qoss2[i]);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST4: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
|
||||
int test5(struct Options options)
|
||||
{
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
#define TOPIC_COUNT 2
|
||||
|
||||
int dup = 0;
|
||||
int msgid = 23;
|
||||
int count = TOPIC_COUNT;
|
||||
MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
|
||||
|
||||
int dup2 = 1;
|
||||
int msgid2 = 2223;
|
||||
int count2 = 0;
|
||||
MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 2 - serialization of unsubscribe and back");
|
||||
|
||||
topicStrings[0].cstring = "mytopic";
|
||||
topicStrings[1].cstring = "mytopic2";
|
||||
rc = MQTTSerialize_unsubscribe(buf, buflen, dup, msgid, count, topicStrings);
|
||||
assert("good rc from serialize unsubscribe", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTDeserialize_unsubscribe(&dup2, &msgid2, 2, &count2, topicStrings2, buf, buflen);
|
||||
assert("good rc from deserialize unsubscribe", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
|
||||
assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
|
||||
|
||||
assert("count should be the same", count == count2, "counts were different %d\n", count2);
|
||||
|
||||
for (i = 0; i < count2; ++i)
|
||||
assert("topics should be the same",
|
||||
checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST5: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int test6(struct Options options)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char buf[100];
|
||||
int buflen = sizeof(buf);
|
||||
|
||||
int connack_rc = 77;
|
||||
|
||||
int connack_rc2 = 0;
|
||||
|
||||
fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
|
||||
global_start_time = start_clock();
|
||||
failures = 0;
|
||||
MyLog(LOGA_INFO, "Starting test 2 - serialization of connack and back");
|
||||
|
||||
rc = MQTTSNSerialize_connack(buf, buflen, connack_rc);
|
||||
assert("good rc from serialize connack", rc > 0, "rc was %d\n", rc);
|
||||
|
||||
rc = MQTTSNDeserialize_connack(&connack_rc2, buf, buflen);
|
||||
assert("good rc from deserialize connack", rc == 1, "rc was %d\n", rc);
|
||||
|
||||
/* data after should be the same as data before */
|
||||
assert("dups should be the same", connack_rc == connack_rc2, "dups were different %d\n", connack_rc2);
|
||||
|
||||
/* exit: */
|
||||
MyLog(LOGA_INFO, "TEST6: test %s. %d tests run, %d failures.",
|
||||
(failures == 0) ? "passed" : "failed", tests, failures);
|
||||
write_test_result();
|
||||
return failures;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int rc = 0;
|
||||
int (*tests[])() = {NULL, test1, test2};
|
||||
|
||||
xml = fopen("TEST-test1.xml", "w");
|
||||
fprintf(xml, "<testsuite name=\"test2\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
|
||||
|
||||
getopts(argc, argv);
|
||||
|
||||
if (options.test_no == 0)
|
||||
{ /* run all the tests */
|
||||
for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
|
||||
rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */
|
||||
}
|
||||
else
|
||||
rc = tests[options.test_no](options); /* run just the selected test */
|
||||
|
||||
if (rc == 0)
|
||||
MyLog(LOGA_INFO, "verdict pass");
|
||||
else
|
||||
MyLog(LOGA_INFO, "verdict fail");
|
||||
|
||||
fprintf(xml, "</testsuite>\n");
|
||||
fclose(xml);
|
||||
return rc;
|
||||
}
|
||||
Reference in New Issue
Block a user