From efede2d9f9df9948a244f587393bfbede43544bf Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Fri, 5 Sep 2014 10:42:21 -0300 Subject: [PATCH] Author: Sergio R. Caprile moved all common socket support functions to a new file (transport). added new samples to show specific actions. Signed-off-by: Sergio R. Caprile --- samples/build | 11 ++- samples/pub0sub1.c | 136 +++++++--------------------------- samples/qos-1pub.c | 122 ++++++------------------------- samples/qos-1pub_extended.c | 72 ++++++++++++++++++ samples/qos0pub.c | 137 ++++++++++------------------------- samples/qos0pub_register.c | 121 +++++++++++++++++++++++++++++++ samples/qos1pub.c | 129 ++++++--------------------------- samples/transport.c | 141 ++++++++++++++++++++++++++++++++++++ samples/transport.h | 21 ++++++ 9 files changed, 471 insertions(+), 419 deletions(-) mode change 100644 => 100755 samples/build create mode 100644 samples/qos-1pub_extended.c create mode 100644 samples/qos0pub_register.c create mode 100644 samples/transport.c create mode 100644 samples/transport.h diff --git a/samples/build b/samples/build old mode 100644 new mode 100755 index 70e7b4e..a6e4937 --- a/samples/build +++ b/samples/build @@ -1,4 +1,7 @@ -gcc -Wall qos0pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos0pub -Os -s -gcc -Wall qos-1pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNPacket.c -o qos-1pub -Os -s -gcc -Wall qos1pub.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c -o qos1pub -Os -s -gcc -Wall pub0sub1.c -I ../src ../src/MQTTSNSerializePublish.c ../src/MQTTSNDeserializePublish.c ../src/MQTTSNPacket.c ../src/MQTTSNConnectClient.c ../src/MQTTSNSubscribeClient.c -o pub0sub1 -Os -s +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 diff --git a/samples/pub0sub1.c b/samples/pub0sub1.c index de35ce0..00f26a0 100644 --- a/samples/pub0sub1.c +++ b/samples/pub0sub1.c @@ -12,111 +12,25 @@ * * 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 "MQTTSNPacket.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 -#include -#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 -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include -#endif -#if defined(WIN32) -#include -#else -#include -#include -#endif - - -int Socket_error(char* aString, int sock) -{ -#if defined(WIN32) - int errno; -#endif - -#if defined(WIN32) - errno = WSAGetLastError(); -#endif - if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) - { - if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) - { - int orig_errno = errno; - char* errmsg = strerror(errno); - - printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock); - } - } - return errno; -} - - -int sendPacketBuffer(int asocket, char* host, int port, unsigned char* buf, int buflen) -{ - struct sockaddr_in cliaddr; - int rc = 0; - - memset(&cliaddr, 0, sizeof(cliaddr)); - cliaddr.sin_family = AF_INET; - cliaddr.sin_addr.s_addr = inet_addr(host); - cliaddr.sin_port = htons(port); - - if ((rc = sendto(asocket, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR) - Socket_error("sendto", asocket); - else if (rc == buflen) - rc = 0; - return rc; -} - - -int mysock = 0; -char *host = "127.0.0.1"; -int port = 1884; - -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; -} +#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; @@ -128,9 +42,15 @@ int main(int argc, char** argv) 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]; @@ -139,16 +59,12 @@ int main(int argc, char** argv) printf("Sending to hostname %s port %d\n", host, port); - mysock = socket(AF_INET, SOCK_DGRAM, 0); - if (mysock == INVALID_SOCKET) - rc = Socket_error("socket", mysock); - options.clientID.cstring = "pub0sub1 MQTT-SN"; len = MQTTSNSerialize_connect(buf, buflen, &options); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); /* wait for connack */ - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_CONNACK) + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_CONNACK) { int connack_rc = -1; @@ -169,10 +85,10 @@ int main(int argc, char** argv) 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, /*msgid*/ 1, &topic); - rc = sendPacketBuffer(mysock, host, port, buf, len); + len = MQTTSNSerialize_subscribe(buf, buflen, 0, 2, packetid, &topic); + rc = transport_sendPacketBuffer(host, port, buf, len); - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_SUBACK) /* wait for suback */ + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_SUBACK) /* wait for suback */ { unsigned short submsgid; int granted_qos; @@ -194,12 +110,13 @@ int main(int argc, char** argv) /* 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 = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); /* wait for puback */ - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_PUBACK) + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_PUBACK) { unsigned short packet_id, topic_id; unsigned char returncode; @@ -213,7 +130,7 @@ int main(int argc, char** argv) goto exit; printf("Receive publish\n"); - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_PUBLISH) + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_PUBLISH) { unsigned short packet_id; int qos, payloadlen; @@ -230,7 +147,7 @@ int main(int argc, char** argv) if (qos == 1) { len = MQTTSNSerialize_puback(buf, buflen, pubtopic.data.id, packet_id, MQTTSN_RC_ACCEPTED); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); if (rc == 0) printf("puback sent\n"); } @@ -239,11 +156,10 @@ int main(int argc, char** argv) goto exit; len = MQTTSNSerialize_disconnect(buf, buflen, 0); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); exit: - rc = shutdown(mysock, SHUT_WR); - rc = close(mysock); + transport_close(); return 0; } diff --git a/samples/qos-1pub.c b/samples/qos-1pub.c index 7113dec..c08a2a9 100644 --- a/samples/qos-1pub.c +++ b/samples/qos-1pub.c @@ -12,135 +12,59 @@ * * 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 "MQTTSNPacket.h" - -#include - -#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 -#include -#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 -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include -#endif -#if defined(WIN32) -#include -#else -#include -#include -#endif - - -int Socket_error(char* aString, int sock) -{ -#if defined(WIN32) - int errno; -#endif - -#if defined(WIN32) - errno = WSAGetLastError(); -#endif - if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) - { - if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) - { - int orig_errno = errno; - char* errmsg = strerror(errno); - - printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock); - } - } - return errno; -} - - -int sendPacketBuffer(int asocket, char* host, int port, unsigned char* buf, int buflen) -{ - struct sockaddr_in cliaddr; - int rc = 0; - - memset(&cliaddr, 0, sizeof(cliaddr)); - cliaddr.sin_family = AF_INET; - cliaddr.sin_addr.s_addr = inet_addr(host); - cliaddr.sin_port = htons(port); - - if ((rc = sendto(asocket, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR) - Socket_error("sendto", asocket); - else - rc = 0; - return rc; -} +#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); - int mysock = 0; 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, packetid = 0; - char *host = argv[1]; - char *topicname = "a long topic name"; + 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); - mysock = socket(AF_INET, SOCK_DGRAM, 0); - if (mysock == INVALID_SOCKET) - rc = Socket_error("socket", mysock); - - topic.type = MQTTSN_TOPIC_TYPE_NORMAL; - topic.data.long_.name = topicname; - topic.data.long_.len = strlen(topicname); - + /* 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 = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); - rc = shutdown(mysock, SHUT_WR); - rc = close(mysock); + transport_close(); return 0; } diff --git a/samples/qos-1pub_extended.c b/samples/qos-1pub_extended.c new file mode 100644 index 0000000..9a08f2b --- /dev/null +++ b/samples/qos-1pub_extended.c @@ -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 +#include +#include + +#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; +} diff --git a/samples/qos0pub.c b/samples/qos0pub.c index ecd2622..d92fe77 100644 --- a/samples/qos0pub.c +++ b/samples/qos0pub.c @@ -12,116 +12,43 @@ * * 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 "MQTTSNPacket.h" - -#include - -#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 -#include -#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 -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include -#endif -#if defined(WIN32) -#include -#else -#include -#include -#endif - - -int Socket_error(char* aString, int sock) -{ -#if defined(WIN32) - int errno; -#endif - -#if defined(WIN32) - errno = WSAGetLastError(); -#endif - if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) - { - if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) - { - int orig_errno = errno; - char* errmsg = strerror(errno); - - printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock); - } - } - return errno; -} - - -int sendPacketBuffer(int asocket, char* host, int port, unsigned char* buf, int buflen) -{ - struct sockaddr_in cliaddr; - int rc = 0; - - memset(&cliaddr, 0, sizeof(cliaddr)); - cliaddr.sin_family = AF_INET; - cliaddr.sin_addr.s_addr = inet_addr(host); - cliaddr.sin_port = htons(port); - - if ((rc = sendto(asocket, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR) - Socket_error("sendto", asocket); - else - rc = 0; - return rc; -} +#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); - int mysock = 0; 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, packetid = 0; + int retained = 0; + short packetid = 0; +// char *topicname = "a long topic name"; char *host = "127.0.0.1"; - char *topicname = "a long topic name"; int port = 1883; MQTTSNPacket_connectData options = MQTTSNPacket_connectData_initializer; + mysock = transport_open(); + if(mysock < 0) + return mysock; + if (argc > 1) host = argv[1]; @@ -130,24 +57,38 @@ int main(int argc, char** argv) printf("Sending to hostname %s port %d\n", host, port); - mysock = socket(AF_INET, SOCK_DGRAM, 0); - if (mysock == INVALID_SOCKET) - rc = Socket_error("socket", mysock); - options.clientID.cstring = "myclientid"; len = MQTTSNSerialize_connect(buf, buflen, &options); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); - topic.type = MQTTSN_TOPIC_TYPE_NORMAL; - topic.data.long_.name = topicname; - topic.data.long_.len = strlen(topicname); + /* 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 = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); printf("rc %d from send packet for publish length %d\n", rc, len); - rc = shutdown(mysock, SHUT_WR); - rc = close(mysock); + +exit: + transport_close(); return 0; } diff --git a/samples/qos0pub_register.c b/samples/qos0pub_register.c new file mode 100644 index 0000000..d8be047 --- /dev/null +++ b/samples/qos0pub_register.c @@ -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 +#include +#include + +#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; + 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 = 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; + + /* register topic name */ + printf("Registering\n"); + 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; + + /* 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 = transport_sendPacketBuffer(host, port, buf, len); + + printf("rc %d from send packet for publish length %d\n", rc, len); + +exit: + transport_close(); + + return 0; +} diff --git a/samples/qos1pub.c b/samples/qos1pub.c index f3d3455..1311fc5 100644 --- a/samples/qos1pub.c +++ b/samples/qos1pub.c @@ -12,113 +12,24 @@ * * 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 "MQTTSNPacket.h" - -#include - -#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 -#include -#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 -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include -#endif -#if defined(WIN32) -#include -#else -#include -#include -#endif - - -int Socket_error(char* aString, int sock) -{ -#if defined(WIN32) - int errno; -#endif - -#if defined(WIN32) - errno = WSAGetLastError(); -#endif - if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) - { - if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) - { - int orig_errno = errno; - char* errmsg = strerror(errno); - - printf("Socket error %d (%s) in %s for socket %d\n", orig_errno, errmsg, aString, sock); - } - } - return errno; -} - - -int sendPacketBuffer(int asocket, char* host, int port, unsigned char* buf, int buflen) -{ - struct sockaddr_in cliaddr; - int rc = 0; - - memset(&cliaddr, 0, sizeof(cliaddr)); - cliaddr.sin_family = AF_INET; - cliaddr.sin_addr.s_addr = inet_addr(host); - cliaddr.sin_port = htons(port); - - if ((rc = sendto(asocket, buf, buflen, 0, (const struct sockaddr*)&cliaddr, sizeof(cliaddr))) == SOCKET_ERROR) - Socket_error("sendto", asocket); - else - rc = 0; - return rc; -} - - -int mysock = 0; -char *host = "127.0.0.1"; -int port = 1884; - -int getdata(unsigned char* buf, int count) -{ - int rc = recvfrom(mysock, buf, count, 0, NULL, NULL); - //printf("received %d bytes count %d\n", rc, (int)count); - return rc; -} +#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; @@ -127,9 +38,16 @@ int main(int argc, char** argv) int len = 0; int dup = 0; int qos = 1; - int retained = 0, packetid = 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]; @@ -138,16 +56,12 @@ int main(int argc, char** argv) printf("Sending to hostname %s port %d\n", host, port); - mysock = socket(AF_INET, SOCK_DGRAM, 0); - if (mysock == INVALID_SOCKET) - rc = Socket_error("socket", mysock); - options.clientID.cstring = "myclientid"; len = MQTTSNSerialize_connect(buf, buflen, &options); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); /* wait for connack */ - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_CONNACK) + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_CONNACK) { int connack_rc = -1; @@ -167,10 +81,10 @@ int main(int argc, char** argv) memcpy(topic.data.short_name, "tt", 2); len = MQTTSNSerialize_publish(buf, buflen - len, dup, qos, retained, packetid, topic, payload, payloadlen); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); /* wait for puback */ - if (MQTTSNPacket_read(buf, buflen, getdata) == MQTTSN_PUBACK) + if (MQTTSNPacket_read(buf, buflen, transport_getdata) == MQTTSN_PUBACK) { unsigned short packet_id, topic_id; unsigned char returncode; @@ -184,11 +98,10 @@ int main(int argc, char** argv) goto exit; len = MQTTSNSerialize_disconnect(buf, buflen, 0); - rc = sendPacketBuffer(mysock, host, port, buf, len); + rc = transport_sendPacketBuffer(host, port, buf, len); exit: - rc = shutdown(mysock, SHUT_WR); - rc = close(mysock); + transport_close(); return 0; } diff --git a/samples/transport.c b/samples/transport.c new file mode 100644 index 0000000..a79ad7d --- /dev/null +++ b/samples/transport.c @@ -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 + +#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 +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(WIN32) +#include +#else +#include +#include +#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; +} diff --git a/samples/transport.h b/samples/transport.h new file mode 100644 index 0000000..e20f1a8 --- /dev/null +++ b/samples/transport.h @@ -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);