├── .cproject ├── .github └── workflows │ └── build_linux.yml ├── .gitignore ├── .project ├── .settings ├── language.settings.xml ├── org.eclipse.cdt.core.prefs └── org.eclipse.cdt.ui.prefs ├── .travis.yml ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Debug ├── makefile ├── objects.mk ├── sources.mk └── src │ ├── MQTTDeserializeConnect.d │ └── subdir.mk ├── LICENSE ├── MQTTClient-C ├── CMakeLists.txt ├── samples │ ├── CMakeLists.txt │ ├── FreeRTOS │ │ └── MQTTEcho.c │ └── linux │ │ ├── CMakeLists.txt │ │ ├── build.sh │ │ └── stdoutsub.c ├── src │ ├── CMakeLists.txt │ ├── FreeRTOS │ │ ├── MQTTFreeRTOS.c │ │ └── MQTTFreeRTOS.h │ ├── MQTTClient.c │ ├── MQTTClient.h │ ├── cc3200 │ │ ├── MQTTCC3200.c │ │ └── MQTTCC3200.h │ └── linux │ │ ├── MQTTLinux.c │ │ └── MQTTLinux.h └── test │ ├── CMakeLists.txt │ └── test1.c ├── MQTTClient ├── CMakeLists.txt ├── samples │ ├── CMakeLists.txt │ ├── arduino │ │ └── Hello │ │ │ └── Hello.ino │ └── linux │ │ ├── CMakeLists.txt │ │ ├── build.sh │ │ ├── hello.cpp │ │ ├── main.cpp │ │ └── stdoutsub.cpp ├── src │ ├── FP.h │ ├── MQTTClient.h │ ├── MQTTLogging.h │ ├── arduino │ │ ├── Countdown.h │ │ ├── IPStack.h │ │ └── WifiIPStack.h │ ├── linux │ │ └── linux.cpp │ └── mbed │ │ ├── MQTTEthernet.h │ │ ├── MQTTSocket.h │ │ └── MQTTmbed.h └── test │ ├── CMakeLists.txt │ └── test1.cpp ├── MQTTPacket ├── CMakeLists.txt ├── samples │ ├── CMakeLists.txt │ ├── baremetalserial │ │ ├── build │ │ ├── ping_nb.c │ │ ├── pub0sub1_nb.c │ │ ├── transport.c │ │ └── transport.h │ ├── build │ ├── null.c │ ├── ping.c │ ├── ping_nb.c │ ├── pub0sub1.c │ ├── pub0sub1_nb.c │ ├── qos0pub.c │ ├── transport.c │ └── transport.h ├── src │ ├── CMakeLists.txt │ ├── MQTTConnect.h │ ├── MQTTConnectClient.c │ ├── MQTTConnectServer.c │ ├── MQTTDeserializePublish.c │ ├── MQTTFormat.c │ ├── MQTTFormat.h │ ├── MQTTPacket.c │ ├── MQTTPacket.h │ ├── MQTTPublish.h │ ├── MQTTSerializePublish.c │ ├── MQTTSubscribe.h │ ├── MQTTSubscribeClient.c │ ├── MQTTSubscribeServer.c │ ├── MQTTUnsubscribe.h │ ├── MQTTUnsubscribeClient.c │ ├── MQTTUnsubscribeServer.c │ └── StackTrace.h └── test │ ├── CMakeLists.txt │ ├── build_test │ └── test1.c ├── Makefile ├── NOTICE ├── README.md ├── SECURITY.md ├── about.html ├── doc ├── DoxyfileMQTTClient-C.in ├── DoxyfileMQTTClient.in ├── DoxyfileMQTTPacket.in └── pahologo.png ├── edl-v10 ├── epl-v10 ├── library.properties ├── notice.html ├── test ├── MQTTV311.py ├── MQTTV3112.py ├── MQTTV5.py ├── mqttsas.py └── mqttsas2.py ├── travis-build.sh ├── travis-env-vars └── travis-install.sh /.github/workflows/build_linux.yml: -------------------------------------------------------------------------------- 1 | name: "Builds for Linux" 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Check out code 9 | uses: actions/checkout@v2 10 | - name: Install dependencies 11 | run: | 12 | sudo apt-get update 13 | sudo apt-get install doxygen 14 | - name: Build 15 | run: | 16 | rm -rf build.paho 17 | mkdir build.paho 18 | cd build.paho 19 | echo "pwd $PWD" 20 | cmake .. 21 | cmake --build . 22 | - name: Start test broker 23 | run: | 24 | git clone https://github.com/eclipse/paho.mqtt.testing.git 25 | cd paho.mqtt.testing/interoperability 26 | python3 startbroker.py -c localhost_testing.conf & 27 | - name: Start test proxy 28 | run: | 29 | python3 test/mqttsas.py localhost 1883 1885 & 30 | - name: run tests 31 | run: | 32 | cd build.paho 33 | ctest -VV --timeout 600 34 | - name: clean up 35 | run: | 36 | killall python3 || true 37 | sleep 3 # allow broker time to terminate and report 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dep/ 2 | /build/ 3 | /build.paho/ 4 | *.swp 5 | *.pyc 6 | /doc/MQTTClient/ 7 | /doc/MQTTPacket/ 8 | /doc/MQTTClient-C/ 9 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | embedded-C 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 24 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 25 | 26 | 27 | -------------------------------------------------------------------------------- /.settings/language.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | formatter_profile=org.eclipse.cdt.ui.default.allman_profile 3 | formatter_settings_version=1 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | language: c 3 | 4 | compiler: 5 | - gcc 6 | 7 | os: 8 | - linux 9 | 10 | sudo: required 11 | 12 | before_install: 13 | - ./travis-install.sh 14 | 15 | script: 16 | - if [[ "$COVERITY_SCAN_BRANCH" != 1 ]]; then ./travis-build.sh; fi 17 | 18 | addons: 19 | apt: 20 | sources: 21 | - george-edison55-precise-backports # cmake 3.2.3 / doxygen 1.8.3 22 | - sourceline: 'ppa:mosquitto-dev/mosquitto-ppa' 23 | packages: 24 | - cmake 25 | - cmake-data 26 | - mosquitto 27 | - doxygen 28 | 29 | 30 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | cmake_minimum_required(VERSION 2.8) 18 | project (embedded-mqtt) 19 | set(CMAKE_BUILD_TYPE Debug) 20 | 21 | message(STATUS "CMake version: " ${CMAKE_VERSION}) 22 | message(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME}) 23 | 24 | set(CMAKE_SCRIPTS "${CMAKE_SOURCE_DIR}/cmake") 25 | set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") 26 | 27 | ## build settings 28 | set(PAHO_VERSION_MAJOR 1) 29 | set(PAHO_VERSION_MINOR 0) 30 | set(PAHO_VERSION_PATCH 0) 31 | set(CLIENT_VERSION ${PAHO_VERSION_MAJOR}.${PAHO_VERSION_MINOR}.${PAHO_VERSION_PATCH}) 32 | 33 | string(TIMESTAMP BUILD_TIMESTAMP UTC) 34 | message(STATUS "Timestamp is ${BUILD_TIMESTAMP}") 35 | 36 | set(CPACK_PACKAGE_VERSION_MAJOR ${PAHO_VERSION_MAJOR}) 37 | set(CPACK_PACKAGE_VERSION_MINOR ${PAHO_VERSION_MINOR}) 38 | set(CPACK_PACKAGE_VERSION_PATCH ${PAHO_VERSION_PATCH}) 39 | include(CPack) 40 | 41 | include_directories(MQTTPacket/src) 42 | 43 | enable_testing() 44 | ADD_SUBDIRECTORY(MQTTPacket) 45 | ADD_SUBDIRECTORY(MQTTClient) 46 | ADD_SUBDIRECTORY(MQTTClient-C) 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Paho 2 | 3 | Thanks for your interest in this project! 4 | 5 | You can contribute bugfixes and new features by sending pull requests through GitHub. 6 | 7 | ## Legal 8 | 9 | In order for your contribution to be accepted, it must comply with the Eclipse Foundation IP policy. 10 | 11 | Please read the [Eclipse Foundation policy on accepting contributions via Git](http://wiki.eclipse.org/Development_Resources/Contributing_via_Git). 12 | 13 | 1. Sign the [Eclipse ECA](http://www.eclipse.org/legal/ECA.php) 14 | 1. Register for an Eclipse Foundation User ID. You can register [here](https://dev.eclipse.org/site_login/createaccount.php). 15 | 2. Log into the [Eclipse projects forge](https://www.eclipse.org/contribute/cla), and click on 'Eclipse Contributor Agreement'. 16 | 2. Go to your [account settings](https://dev.eclipse.org/site_login/myaccount.php#open_tab_accountsettings) and add your GitHub username to your account. 17 | 3. Make sure that you _sign-off_ your Git commits in the following format: 18 | ``` Signed-off-by: Alex Smith ``` This is usually at the bottom of the commit message. You can automate this by adding the '-s' flag when you make the commits. e.g. ```git commit -s -m "Adding a cool feature"``` 19 | 4. Ensure that the email address that you make your commits with is the same one you used to sign up to the Eclipse Foundation website with. 20 | 21 | ## Contributing a change 22 | 23 | 1. [Fork the repository on GitHub](https://github.com/eclipse/paho.mqtt.embedded-c/fork) 24 | 2. Clone the forked repository onto your computer: ``` git clone https://github.com//paho.mqtt.embedded-c.git ``` 25 | 3. Create a new branch from the latest ```develop``` branch with ```git checkout -b YOUR_BRANCH_NAME origin/develop``` 26 | 4. Make your changes 27 | 5. If developing a new feature, make sure to include JUnit tests. 28 | 6. Ensure that all new and existing tests pass. 29 | 7. Commit the changes into the branch: ``` git commit -s ``` Make sure that your commit message is meaningful and describes your changes correctly. 30 | 8. If you have a lot of commits for the change, squash them into a single / few commits. 31 | 9. Push the changes in your branch to your forked repository. 32 | 10. Finally, go to [https://github.com/eclipse/paho.mqtt.embedded-c](https://github.com/eclipse/paho.mqtt.embedded-c) and create a pull request from your "YOUR_BRANCH_NAME" branch to the ```develop``` one to request review and merge of the commits in your pushed branch. 33 | 34 | 35 | What happens next depends on the content of the patch. If it is 100% authored 36 | by the contributor and is less than 1000 lines (and meets the needs of the 37 | project), then it can be pulled into the main repository. If not, more steps 38 | are required. These are detailed in the 39 | [legal process poster](http://www.eclipse.org/legal/EclipseLegalProcessPoster.pdf). 40 | 41 | 42 | 43 | ## Developer resources: 44 | 45 | 46 | Information regarding source code management, builds, coding standards, and more. 47 | 48 | - [https://projects.eclipse.org/projects/iot.paho/developer](https://projects.eclipse.org/projects/iot.paho/developer) 49 | 50 | Contact: 51 | -------- 52 | 53 | Contact the project developers via the project's development 54 | [mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev). 55 | 56 | Search for bugs: 57 | ---------------- 58 | 59 | This project uses GitHub Issues here: [github.com/eclipse/paho.mqtt.embedded-c/issues](https://github.com/eclipse/paho.mqtt.embedded-c/issues) to track ongoing development and issues. 60 | 61 | Create a new bug: 62 | ----------------- 63 | 64 | Be sure to search for existing bugs before you create another one. Remember that contributions are always welcome! 65 | 66 | - [Create new Paho bug](https://github.com/eclipse/paho.mqtt.embedded-c/issues) 67 | -------------------------------------------------------------------------------- /Debug/makefile: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | -include ../makefile.init 6 | 7 | RM := rm -rf 8 | 9 | # All of the sources participating in the build are defined here 10 | -include sources.mk 11 | -include MQTTPacket/src/subdir.mk 12 | -include MQTTPacket/samples/subdir.mk 13 | -include subdir.mk 14 | -include objects.mk 15 | 16 | ifneq ($(MAKECMDGOALS),clean) 17 | ifneq ($(strip $(C_DEPS)),) 18 | -include $(C_DEPS) 19 | endif 20 | endif 21 | 22 | -include ../makefile.defs 23 | 24 | # Add inputs and outputs from these tool invocations to the build variables 25 | 26 | # All Target 27 | all: libembedded-C.so 28 | 29 | # Tool invocations 30 | libembedded-C.so: $(OBJS) $(USER_OBJS) 31 | @echo 'Building target: $@' 32 | @echo 'Invoking: GCC C Linker' 33 | gcc -shared -o "libembedded-C.so" $(OBJS) $(USER_OBJS) $(LIBS) 34 | @echo 'Finished building target: $@' 35 | @echo ' ' 36 | 37 | # Other Targets 38 | clean: 39 | -$(RM) $(C_DEPS)$(LIBRARIES)$(OBJS) libembedded-C.so 40 | -@echo ' ' 41 | 42 | .PHONY: all clean dependents 43 | .SECONDARY: 44 | 45 | -include ../makefile.targets 46 | -------------------------------------------------------------------------------- /Debug/objects.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | USER_OBJS := 6 | 7 | LIBS := 8 | 9 | -------------------------------------------------------------------------------- /Debug/sources.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | ASM_SRCS := 6 | OBJ_SRCS := 7 | S_UPPER_SRCS := 8 | C_SRCS := 9 | O_SRCS := 10 | C_DEPS := 11 | LIBRARIES := 12 | OBJS := 13 | 14 | # Every subdirectory with source files must be described here 15 | SUBDIRS := \ 16 | MQTTPacket/src \ 17 | MQTTPacket/samples \ 18 | 19 | -------------------------------------------------------------------------------- /Debug/src/MQTTDeserializeConnect.d: -------------------------------------------------------------------------------- 1 | src/MQTTDeserializeConnect.d src/MQTTDeserializeConnect.o: \ 2 | ../src/MQTTDeserializeConnect.c ../src/StackTrace.h 3 | 4 | ../src/StackTrace.h: 5 | -------------------------------------------------------------------------------- /Debug/src/subdir.mk: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Automatically-generated file. Do not edit! 3 | ################################################################################ 4 | 5 | # Add inputs and outputs from these tool invocations to the build variables 6 | C_SRCS += \ 7 | ../src/MQTTConnectClient.c \ 8 | ../src/MQTTConnectServer.c \ 9 | ../src/MQTTDeserializePublish.c \ 10 | ../src/MQTTPacket.c \ 11 | ../src/MQTTSerializePublish.c \ 12 | ../src/MQTTSubscribeClient.c \ 13 | ../src/MQTTSubscribeServer.c \ 14 | ../src/MQTTUnsubscribeClient.c \ 15 | ../src/MQTTUnsubscribeServer.c 16 | 17 | C_DEPS += \ 18 | ./src/MQTTConnectClient.d \ 19 | ./src/MQTTConnectServer.d \ 20 | ./src/MQTTDeserializePublish.d \ 21 | ./src/MQTTPacket.d \ 22 | ./src/MQTTSerializePublish.d \ 23 | ./src/MQTTSubscribeClient.d \ 24 | ./src/MQTTSubscribeServer.d \ 25 | ./src/MQTTUnsubscribeClient.d \ 26 | ./src/MQTTUnsubscribeServer.d 27 | 28 | OBJS += \ 29 | ./src/MQTTConnectClient.o \ 30 | ./src/MQTTConnectServer.o \ 31 | ./src/MQTTDeserializePublish.o \ 32 | ./src/MQTTPacket.o \ 33 | ./src/MQTTSerializePublish.o \ 34 | ./src/MQTTSubscribeClient.o \ 35 | ./src/MQTTSubscribeServer.o \ 36 | ./src/MQTTUnsubscribeClient.o \ 37 | ./src/MQTTUnsubscribeServer.o 38 | 39 | 40 | # Each subdirectory must supply rules for building sources it contributes 41 | src/%.o: ../src/%.c 42 | @echo 'Building file: $<' 43 | @echo 'Invoking: GCC C Compiler' 44 | gcc -I"/home/icraggs/work/paho/org.eclipse.paho.mqtt.embedded-c/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" 45 | @echo 'Finished building: $<' 46 | @echo ' ' 47 | 48 | 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 2.0 2 | 3 | This program and the accompanying materials 4 | are made available under the terms of the Eclipse Public License v2.0 5 | and Eclipse Distribution License v1.0 which accompany this distribution. 6 | 7 | The Eclipse Public License is available at 8 | https://www.eclipse.org/legal/epl-2.0/ 9 | and the Eclipse Distribution License is available at 10 | http://www.eclipse.org/org/documents/edl-v10.php. 11 | 12 | For an explanation of what dual-licensing means to you, see: 13 | https://www.eclipse.org/legal/eplfaq.php#DUALLIC 14 | -------------------------------------------------------------------------------- /MQTTClient-C/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | project("paho-mqttclient" C) 18 | 19 | ADD_SUBDIRECTORY(src) 20 | ADD_SUBDIRECTORY(samples) 21 | ADD_SUBDIRECTORY(test) 22 | -------------------------------------------------------------------------------- /MQTTClient-C/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | add_subdirectory(linux) 18 | -------------------------------------------------------------------------------- /MQTTClient-C/samples/FreeRTOS/MQTTEcho.c: -------------------------------------------------------------------------------- 1 | /* Standard includes. */ 2 | #include 3 | #include 4 | #include 5 | 6 | /* FreeRTOS includes. */ 7 | #include "FreeRTOS.h" 8 | #include "task.h" 9 | #include "queue.h" 10 | 11 | /* FreeRTOS+TCP includes. */ 12 | #include "FreeRTOS_IP.h" 13 | #include "FreeRTOS_Sockets.h" 14 | 15 | #define MQTT_TASK 1 16 | #include "MQTTClient.h" 17 | 18 | 19 | void messageArrived(MessageData* data) 20 | { 21 | printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data, 22 | data->message->payloadlen, data->message->payload); 23 | } 24 | 25 | static void prvMQTTEchoTask(void *pvParameters) 26 | { 27 | /* connect to m2m.eclipse.org, subscribe to a topic, send and receive messages regularly every 1 sec */ 28 | MQTTClient client; 29 | Network network; 30 | unsigned char sendbuf[80], readbuf[80]; 31 | int rc = 0, 32 | count = 0; 33 | MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer; 34 | 35 | pvParameters = 0; 36 | NetworkInit(&network); 37 | MQTTClientInit(&client, &network, 30000, sendbuf, sizeof(sendbuf), readbuf, sizeof(readbuf)); 38 | 39 | char* address = "iot.eclipse.org"; 40 | if ((rc = NetworkConnect(&network, address, 1883)) != 0) 41 | printf("Return code from network connect is %d\n", rc); 42 | 43 | #if defined(MQTT_TASK) 44 | if ((rc = MQTTStartTask(&client)) != pdPASS) 45 | printf("Return code from start tasks is %d\n", rc); 46 | #endif 47 | 48 | connectData.MQTTVersion = 3; 49 | connectData.clientID.cstring = "FreeRTOS_sample"; 50 | 51 | if ((rc = MQTTConnect(&client, &connectData)) != 0) 52 | printf("Return code from MQTT connect is %d\n", rc); 53 | else 54 | printf("MQTT Connected\n"); 55 | 56 | if ((rc = MQTTSubscribe(&client, "FreeRTOS/sample/#", 2, messageArrived)) != 0) 57 | printf("Return code from MQTT subscribe is %d\n", rc); 58 | 59 | while (++count) 60 | { 61 | MQTTMessage message; 62 | char payload[30]; 63 | 64 | message.qos = 1; 65 | message.retained = 0; 66 | message.payload = payload; 67 | sprintf(payload, "message number %d", count); 68 | message.payloadlen = strlen(payload); 69 | 70 | if ((rc = MQTTPublish(&client, "FreeRTOS/sample/a", &message)) != 0) 71 | printf("Return code from MQTT publish is %d\n", rc); 72 | #if !defined(MQTT_TASK) 73 | if ((rc = MQTTYield(&client, 1000)) != 0) 74 | printf("Return code from yield is %d\n", rc); 75 | #endif 76 | } 77 | 78 | /* do not return */ 79 | } 80 | 81 | 82 | void vStartMQTTTasks(uint16_t usTaskStackSize, UBaseType_t uxTaskPriority) 83 | { 84 | BaseType_t x = 0L; 85 | 86 | xTaskCreate(prvMQTTEchoTask, /* The function that implements the task. */ 87 | "MQTTEcho0", /* Just a text name for the task to aid debugging. */ 88 | usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ 89 | (void *)x, /* The task parameter, not used in this case. */ 90 | uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ 91 | NULL); /* The task handle is not used. */ 92 | } 93 | /*-----------------------------------------------------------*/ 94 | 95 | 96 | -------------------------------------------------------------------------------- /MQTTClient-C/samples/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | 18 | add_executable( 19 | stdoutsubc 20 | stdoutsub.c 21 | ) 22 | target_link_libraries(stdoutsubc paho-embed-mqtt3cc paho-embed-mqtt3c) 23 | target_include_directories(stdoutsubc PRIVATE "../../src" "../../src/linux") 24 | target_compile_definitions(stdoutsubc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h) 25 | -------------------------------------------------------------------------------- /MQTTClient-C/samples/linux/build.sh: -------------------------------------------------------------------------------- 1 | cp ../../src/MQTTClient.c . 2 | sed -e 's/""/"MQTTLinux.h"/g' ../../src/MQTTClient.h > MQTTClient.h 3 | gcc stdoutsub.c -I ../../src -I ../../src/linux -I ../../../MQTTPacket/src MQTTClient.c ../../src/linux/MQTTLinux.c ../../../MQTTPacket/src/MQTTFormat.c ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c -o stdoutsub ../../../MQTTPacket/src/MQTTConnectServer.c ../../../MQTTPacket/src/MQTTSubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c -DMQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h 4 | -------------------------------------------------------------------------------- /MQTTClient-C/samples/linux/stdoutsub.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2012, 2016 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial contribution 15 | * Ian Craggs - change delimiter option from char to string 16 | * Al Stockdill-Mander - Version using the embedded C client 17 | * Ian Craggs - update MQTTClient function names 18 | *******************************************************************************/ 19 | 20 | /* 21 | 22 | stdout subscriber 23 | 24 | compulsory parameters: 25 | 26 | topic to subscribe to 27 | 28 | defaulted parameters: 29 | 30 | --host localhost 31 | --port 1883 32 | --qos 2 33 | --delimiter \n 34 | --clientid stdout_subscriber 35 | 36 | --userid none 37 | --password none 38 | 39 | for example: 40 | 41 | stdoutsub topic/of/interest --host iot.eclipse.org 42 | 43 | */ 44 | #include 45 | #include 46 | #include "MQTTClient.h" 47 | 48 | #include 49 | #include 50 | 51 | #include 52 | 53 | 54 | volatile int toStop = 0; 55 | 56 | 57 | void usage() 58 | { 59 | printf("MQTT stdout subscriber\n"); 60 | printf("Usage: stdoutsub topicname , where options are:\n"); 61 | printf(" --host (default is localhost)\n"); 62 | printf(" --port (default is 1883)\n"); 63 | printf(" --qos (default is 2)\n"); 64 | printf(" --delimiter (default is \\n)\n"); 65 | printf(" --clientid (default is hostname+timestamp)\n"); 66 | printf(" --username none\n"); 67 | printf(" --password none\n"); 68 | printf(" --showtopics (default is on if the topic has a wildcard, else off)\n"); 69 | exit(-1); 70 | } 71 | 72 | 73 | void cfinish(int sig) 74 | { 75 | signal(SIGINT, NULL); 76 | toStop = 1; 77 | } 78 | 79 | 80 | struct opts_struct 81 | { 82 | char* clientid; 83 | int nodelimiter; 84 | char* delimiter; 85 | enum QoS qos; 86 | char* username; 87 | char* password; 88 | char* host; 89 | int port; 90 | int showtopics; 91 | } opts = 92 | { 93 | (char*)"stdout-subscriber", 0, (char*)"\n", QOS2, NULL, NULL, (char*)"localhost", 1883, 0 94 | }; 95 | 96 | 97 | void getopts(int argc, char** argv) 98 | { 99 | int count = 2; 100 | 101 | while (count < argc) 102 | { 103 | if (strcmp(argv[count], "--qos") == 0) 104 | { 105 | if (++count < argc) 106 | { 107 | if (strcmp(argv[count], "0") == 0) 108 | opts.qos = QOS0; 109 | else if (strcmp(argv[count], "1") == 0) 110 | opts.qos = QOS1; 111 | else if (strcmp(argv[count], "2") == 0) 112 | opts.qos = QOS2; 113 | else 114 | usage(); 115 | } 116 | else 117 | usage(); 118 | } 119 | else if (strcmp(argv[count], "--host") == 0) 120 | { 121 | if (++count < argc) 122 | opts.host = argv[count]; 123 | else 124 | usage(); 125 | } 126 | else if (strcmp(argv[count], "--port") == 0) 127 | { 128 | if (++count < argc) 129 | opts.port = atoi(argv[count]); 130 | else 131 | usage(); 132 | } 133 | else if (strcmp(argv[count], "--clientid") == 0) 134 | { 135 | if (++count < argc) 136 | opts.clientid = argv[count]; 137 | else 138 | usage(); 139 | } 140 | else if (strcmp(argv[count], "--username") == 0) 141 | { 142 | if (++count < argc) 143 | opts.username = argv[count]; 144 | else 145 | usage(); 146 | } 147 | else if (strcmp(argv[count], "--password") == 0) 148 | { 149 | if (++count < argc) 150 | opts.password = argv[count]; 151 | else 152 | usage(); 153 | } 154 | else if (strcmp(argv[count], "--delimiter") == 0) 155 | { 156 | if (++count < argc) 157 | opts.delimiter = argv[count]; 158 | else 159 | opts.nodelimiter = 1; 160 | } 161 | else if (strcmp(argv[count], "--showtopics") == 0) 162 | { 163 | if (++count < argc) 164 | { 165 | if (strcmp(argv[count], "on") == 0) 166 | opts.showtopics = 1; 167 | else if (strcmp(argv[count], "off") == 0) 168 | opts.showtopics = 0; 169 | else 170 | usage(); 171 | } 172 | else 173 | usage(); 174 | } 175 | count++; 176 | } 177 | 178 | } 179 | 180 | 181 | void messageArrived(MessageData* md) 182 | { 183 | MQTTMessage* message = md->message; 184 | 185 | if (opts.showtopics) 186 | printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data); 187 | if (opts.nodelimiter) 188 | printf("%.*s", (int)message->payloadlen, (char*)message->payload); 189 | else 190 | printf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter); 191 | //fflush(stdout); 192 | } 193 | 194 | 195 | int main(int argc, char** argv) 196 | { 197 | int rc = 0; 198 | unsigned char buf[100]; 199 | unsigned char readbuf[100]; 200 | 201 | if (argc < 2) 202 | usage(); 203 | 204 | char* topic = argv[1]; 205 | 206 | if (strchr(topic, '#') || strchr(topic, '+')) 207 | opts.showtopics = 1; 208 | if (opts.showtopics) 209 | printf("topic is %s\n", topic); 210 | 211 | getopts(argc, argv); 212 | 213 | Network n; 214 | MQTTClient c; 215 | 216 | signal(SIGINT, cfinish); 217 | signal(SIGTERM, cfinish); 218 | 219 | NetworkInit(&n); 220 | NetworkConnect(&n, opts.host, opts.port); 221 | MQTTClientInit(&c, &n, 1000, buf, 100, readbuf, 100); 222 | 223 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 224 | data.willFlag = 0; 225 | data.MQTTVersion = 3; 226 | data.clientID.cstring = opts.clientid; 227 | data.username.cstring = opts.username; 228 | data.password.cstring = opts.password; 229 | 230 | data.keepAliveInterval = 10; 231 | data.cleansession = 1; 232 | printf("Connecting to %s %d\n", opts.host, opts.port); 233 | 234 | rc = MQTTConnect(&c, &data); 235 | printf("Connected %d\n", rc); 236 | 237 | printf("Subscribing to %s\n", topic); 238 | rc = MQTTSubscribe(&c, topic, opts.qos, messageArrived); 239 | printf("Subscribed %d\n", rc); 240 | 241 | while (!toStop) 242 | { 243 | MQTTYield(&c, 1000); 244 | } 245 | 246 | printf("Stopping\n"); 247 | 248 | MQTTDisconnect(&c); 249 | NetworkDisconnect(&n); 250 | 251 | return 0; 252 | } 253 | 254 | 255 | -------------------------------------------------------------------------------- /MQTTClient-C/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | # MQTTClient Library - C 18 | 19 | 20 | file(GLOB SOURCES "*.c" "linux/*.c") 21 | 22 | add_library( 23 | paho-embed-mqtt3cc SHARED 24 | ${SOURCES} 25 | ) 26 | install(TARGETS paho-embed-mqtt3cc DESTINATION /usr/lib) 27 | target_include_directories(paho-embed-mqtt3cc PRIVATE "linux") 28 | target_link_libraries(paho-embed-mqtt3cc paho-embed-mqtt3c) 29 | target_compile_definitions(paho-embed-mqtt3cc PRIVATE 30 | MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h MQTTCLIENT_QOS2=1) 31 | -------------------------------------------------------------------------------- /MQTTClient-C/src/FreeRTOS/MQTTFreeRTOS.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2015 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #if !defined(MQTTFreeRTOS_H) 18 | #define MQTTFreeRTOS_H 19 | 20 | #include "FreeRTOS.h" 21 | #include "FreeRTOS_Sockets.h" 22 | #include "FreeRTOS_IP.h" 23 | #include "semphr.h" 24 | #include "task.h" 25 | 26 | typedef struct Timer 27 | { 28 | TickType_t xTicksToWait; 29 | TimeOut_t xTimeOut; 30 | } Timer; 31 | 32 | typedef struct Network Network; 33 | 34 | struct Network 35 | { 36 | xSocket_t my_socket; 37 | int (*mqttread) (Network*, unsigned char*, int, int); 38 | int (*mqttwrite) (Network*, unsigned char*, int, int); 39 | void (*disconnect) (Network*); 40 | }; 41 | 42 | void TimerInit(Timer*); 43 | char TimerIsExpired(Timer*); 44 | void TimerCountdownMS(Timer*, unsigned int); 45 | void TimerCountdown(Timer*, unsigned int); 46 | int TimerLeftMS(Timer*); 47 | 48 | typedef struct Mutex 49 | { 50 | SemaphoreHandle_t sem; 51 | } Mutex; 52 | 53 | void MutexInit(Mutex*); 54 | int MutexLock(Mutex*); 55 | int MutexUnlock(Mutex*); 56 | 57 | typedef struct Thread 58 | { 59 | TaskHandle_t task; 60 | } Thread; 61 | 62 | int ThreadStart(Thread*, void (*fn)(void*), void* arg); 63 | 64 | int FreeRTOS_read(Network*, unsigned char*, int, int); 65 | int FreeRTOS_write(Network*, unsigned char*, int, int); 66 | void FreeRTOS_disconnect(Network*); 67 | 68 | void NetworkInit(Network*); 69 | int NetworkConnect(Network*, char*, int); 70 | /*int NetworkConnectTLS(Network*, char*, int, SlSockSecureFiles_t*, unsigned char, unsigned int, char);*/ 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /MQTTClient-C/src/cc3200/MQTTCC3200.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTCC3200.h" 18 | 19 | unsigned long MilliTimer; 20 | 21 | void SysTickIntHandler(void) { 22 | MilliTimer++; 23 | } 24 | 25 | char expired(Timer* timer) { 26 | long left = timer->end_time - MilliTimer; 27 | return (left < 0); 28 | } 29 | 30 | 31 | void countdown_ms(Timer* timer, unsigned int timeout) { 32 | timer->end_time = MilliTimer + timeout; 33 | } 34 | 35 | 36 | void countdown(Timer* timer, unsigned int timeout) { 37 | timer->end_time = MilliTimer + (timeout * 1000); 38 | } 39 | 40 | 41 | int left_ms(Timer* timer) { 42 | long left = timer->end_time - MilliTimer; 43 | return (left < 0) ? 0 : left; 44 | } 45 | 46 | 47 | void InitTimer(Timer* timer) { 48 | timer->end_time = 0; 49 | } 50 | 51 | 52 | int cc3200_read(Network* n, unsigned char* buffer, int len, int timeout_ms) { 53 | SlTimeval_t timeVal; 54 | SlFdSet_t fdset; 55 | int rc = 0; 56 | int recvLen = 0; 57 | 58 | SL_FD_ZERO(&fdset); 59 | SL_FD_SET(n->my_socket, &fdset); 60 | 61 | timeVal.tv_sec = 0; 62 | timeVal.tv_usec = timeout_ms * 1000; 63 | if (sl_Select(n->my_socket + 1, &fdset, NULL, NULL, &timeVal) == 1) { 64 | do { 65 | rc = sl_Recv(n->my_socket, buffer + recvLen, len - recvLen, 0); 66 | recvLen += rc; 67 | } while(recvLen < len); 68 | } 69 | return recvLen; 70 | } 71 | 72 | 73 | int cc3200_write(Network* n, unsigned char* buffer, int len, int timeout_ms) { 74 | SlTimeval_t timeVal; 75 | SlFdSet_t fdset; 76 | int rc = 0; 77 | int readySock; 78 | 79 | SL_FD_ZERO(&fdset); 80 | SL_FD_SET(n->my_socket, &fdset); 81 | 82 | timeVal.tv_sec = 0; 83 | timeVal.tv_usec = timeout_ms * 1000; 84 | do { 85 | readySock = sl_Select(n->my_socket + 1, NULL, &fdset, NULL, &timeVal); 86 | } while(readySock != 1); 87 | rc = sl_Send(n->my_socket, buffer, len, 0); 88 | return rc; 89 | } 90 | 91 | 92 | void cc3200_disconnect(Network* n) { 93 | sl_Close(n->my_socket); 94 | } 95 | 96 | 97 | void NewNetwork(Network* n) { 98 | n->my_socket = 0; 99 | n->mqttread = cc3200_read; 100 | n->mqttwrite = cc3200_write; 101 | n->disconnect = cc3200_disconnect; 102 | } 103 | 104 | int TLSConnectNetwork(Network *n, char* addr, int port, SlSockSecureFiles_t* certificates, unsigned char sec_method, unsigned int cipher, char server_verify) { 105 | SlSockAddrIn_t sAddr; 106 | int addrSize; 107 | int retVal; 108 | unsigned long ipAddress; 109 | 110 | retVal = sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET); 111 | if (retVal < 0) { 112 | return -1; 113 | } 114 | 115 | sAddr.sin_family = AF_INET; 116 | sAddr.sin_port = sl_Htons((unsigned short)port); 117 | sAddr.sin_addr.s_addr = sl_Htonl(ipAddress); 118 | 119 | addrSize = sizeof(SlSockAddrIn_t); 120 | 121 | n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); 122 | if (n->my_socket < 0) { 123 | return -1; 124 | } 125 | 126 | SlSockSecureMethod method; 127 | method.secureMethod = sec_method; 128 | retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method)); 129 | if (retVal < 0) { 130 | return retVal; 131 | } 132 | 133 | SlSockSecureMask mask; 134 | mask.secureMask = cipher; 135 | retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &mask, sizeof(mask)); 136 | if (retVal < 0) { 137 | return retVal; 138 | } 139 | 140 | if (certificates != NULL) { 141 | retVal = sl_SetSockOpt(n->my_socket, SL_SOL_SOCKET, SL_SO_SECURE_FILES, certificates->secureFiles, sizeof(SlSockSecureFiles_t)); 142 | if(retVal < 0) 143 | { 144 | return retVal; 145 | } 146 | } 147 | 148 | retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize); 149 | if( retVal < 0 ) { 150 | if (server_verify || retVal != -453) { 151 | sl_Close(n->my_socket); 152 | return retVal; 153 | } 154 | } 155 | 156 | SysTickIntRegister(SysTickIntHandler); 157 | SysTickPeriodSet(80000); 158 | SysTickEnable(); 159 | 160 | return retVal; 161 | } 162 | 163 | int ConnectNetwork(Network* n, char* addr, int port) 164 | { 165 | SlSockAddrIn_t sAddr; 166 | int addrSize; 167 | int retVal; 168 | unsigned long ipAddress; 169 | 170 | sl_NetAppDnsGetHostByName(addr, strlen(addr), &ipAddress, AF_INET); 171 | 172 | sAddr.sin_family = AF_INET; 173 | sAddr.sin_port = sl_Htons((unsigned short)port); 174 | sAddr.sin_addr.s_addr = sl_Htonl(ipAddress); 175 | 176 | addrSize = sizeof(SlSockAddrIn_t); 177 | 178 | n->my_socket = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); 179 | if( n->my_socket < 0 ) { 180 | // error 181 | return -1; 182 | } 183 | 184 | retVal = sl_Connect(n->my_socket, ( SlSockAddr_t *)&sAddr, addrSize); 185 | if( retVal < 0 ) { 186 | // error 187 | sl_Close(n->my_socket); 188 | return retVal; 189 | } 190 | 191 | SysTickIntRegister(SysTickIntHandler); 192 | SysTickPeriodSet(80000); 193 | SysTickEnable(); 194 | 195 | return retVal; 196 | } 197 | -------------------------------------------------------------------------------- /MQTTClient-C/src/cc3200/MQTTCC3200.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #ifndef __MQTT_CC3200_ 18 | #define __MQTT_CC3200_ 19 | 20 | #include "simplelink.h" 21 | #include "netapp.h" 22 | #include "socket.h" 23 | #include "hw_types.h" 24 | #include "systick.h" 25 | 26 | typedef struct Timer Timer; 27 | 28 | struct Timer { 29 | unsigned long systick_period; 30 | unsigned long end_time; 31 | }; 32 | 33 | typedef struct Network Network; 34 | 35 | struct Network 36 | { 37 | int my_socket; 38 | int (*mqttread) (Network*, unsigned char*, int, int); 39 | int (*mqttwrite) (Network*, unsigned char*, int, int); 40 | void (*disconnect) (Network*); 41 | }; 42 | 43 | char expired(Timer*); 44 | void countdown_ms(Timer*, unsigned int); 45 | void countdown(Timer*, unsigned int); 46 | int left_ms(Timer*); 47 | 48 | void InitTimer(Timer*); 49 | 50 | int cc3200_read(Network*, unsigned char*, int, int); 51 | int cc3200_write(Network*, unsigned char*, int, int); 52 | void cc3200_disconnect(Network*); 53 | void NewNetwork(Network*); 54 | 55 | int ConnectNetwork(Network*, char*, int); 56 | int TLSConnectNetwork(Network*, char*, int, SlSockSecureFiles_t*, unsigned char, unsigned int, char); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /MQTTClient-C/src/linux/MQTTLinux.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2023 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander - initial API and implementation and/or initial documentation 15 | * Ian Craggs - return codes from linux_read 16 | *******************************************************************************/ 17 | 18 | #include "MQTTLinux.h" 19 | 20 | void TimerInit(Timer* timer) 21 | { 22 | timer->end_time = (struct timeval){0, 0}; 23 | } 24 | 25 | char TimerIsExpired(Timer* timer) 26 | { 27 | struct timeval now, res; 28 | gettimeofday(&now, NULL); 29 | timersub(&timer->end_time, &now, &res); 30 | return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); 31 | } 32 | 33 | 34 | void TimerCountdownMS(Timer* timer, unsigned int timeout) 35 | { 36 | struct timeval now; 37 | gettimeofday(&now, NULL); 38 | struct timeval interval = {timeout / 1000, (timeout % 1000) * 1000}; 39 | timeradd(&now, &interval, &timer->end_time); 40 | } 41 | 42 | 43 | void TimerCountdown(Timer* timer, unsigned int timeout) 44 | { 45 | struct timeval now; 46 | gettimeofday(&now, NULL); 47 | struct timeval interval = {timeout, 0}; 48 | timeradd(&now, &interval, &timer->end_time); 49 | } 50 | 51 | 52 | int TimerLeftMS(Timer* timer) 53 | { 54 | struct timeval now, res; 55 | gettimeofday(&now, NULL); 56 | timersub(&timer->end_time, &now, &res); 57 | //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); 58 | return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000; 59 | } 60 | 61 | 62 | int linux_read(Network* n, unsigned char* buffer, int len, int timeout_ms) 63 | { 64 | struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000}; 65 | if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0)) 66 | { 67 | interval.tv_sec = 0; 68 | interval.tv_usec = 100; 69 | } 70 | 71 | setsockopt(n->my_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval)); 72 | 73 | int bytes = 0; 74 | while (bytes < len) 75 | { 76 | int rc = recv(n->my_socket, &buffer[bytes], (size_t)(len - bytes), 0); 77 | if (rc == -1) 78 | { 79 | if (errno != EAGAIN && errno != EWOULDBLOCK) 80 | bytes = -1; 81 | break; 82 | } 83 | else if (rc == 0) 84 | { 85 | bytes = 0; 86 | break; 87 | } 88 | else 89 | bytes += rc; 90 | } 91 | return bytes; 92 | } 93 | 94 | 95 | int linux_write(Network* n, unsigned char* buffer, int len, int timeout_ms) 96 | { 97 | struct timeval tv; 98 | 99 | tv.tv_sec = 0; /* 30 Secs Timeout */ 100 | tv.tv_usec = timeout_ms * 1000; // Not init'ing this can cause strange errors 101 | 102 | setsockopt(n->my_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval)); 103 | int rc = write(n->my_socket, buffer, len); 104 | return rc; 105 | } 106 | 107 | 108 | void NetworkInit(Network* n) 109 | { 110 | signal(SIGPIPE, SIG_IGN); 111 | n->my_socket = 0; 112 | n->mqttread = linux_read; 113 | n->mqttwrite = linux_write; 114 | } 115 | 116 | 117 | int NetworkConnect(Network* n, char* addr, int port) 118 | { 119 | int type = SOCK_STREAM; 120 | struct sockaddr_in address; 121 | int rc = -1; 122 | sa_family_t family = AF_INET; 123 | struct addrinfo *result = NULL; 124 | struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL}; 125 | 126 | if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0) 127 | { 128 | struct addrinfo* res = result; 129 | 130 | /* prefer ip4 addresses */ 131 | while (res) 132 | { 133 | if (res->ai_family == AF_INET) 134 | { 135 | result = res; 136 | break; 137 | } 138 | res = res->ai_next; 139 | } 140 | 141 | if (result->ai_family == AF_INET) 142 | { 143 | address.sin_port = htons(port); 144 | address.sin_family = family = AF_INET; 145 | address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr; 146 | } 147 | else 148 | rc = -1; 149 | 150 | freeaddrinfo(result); 151 | } 152 | 153 | if (rc == 0) 154 | { 155 | n->my_socket = socket(family, type, 0); 156 | if (n->my_socket != -1) 157 | rc = connect(n->my_socket, (struct sockaddr*)&address, sizeof(address)); 158 | else 159 | rc = -1; 160 | } 161 | 162 | return rc; 163 | } 164 | 165 | 166 | void NetworkDisconnect(Network* n) 167 | { 168 | close(n->my_socket); 169 | } 170 | -------------------------------------------------------------------------------- /MQTTClient-C/src/linux/MQTTLinux.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Allan Stockdill-Mander - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #if !defined(__MQTT_LINUX_) 18 | #define __MQTT_LINUX_ 19 | 20 | #if defined(WIN32_DLL) || defined(WIN64_DLL) 21 | #define DLLImport __declspec(dllimport) 22 | #define DLLExport __declspec(dllexport) 23 | #elif defined(LINUX_SO) 24 | #define DLLImport extern 25 | #define DLLExport __attribute__ ((visibility ("default"))) 26 | #else 27 | #define DLLImport 28 | #define DLLExport 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | typedef struct Timer 50 | { 51 | struct timeval end_time; 52 | } Timer; 53 | 54 | void TimerInit(Timer*); 55 | char TimerIsExpired(Timer*); 56 | void TimerCountdownMS(Timer*, unsigned int); 57 | void TimerCountdown(Timer*, unsigned int); 58 | int TimerLeftMS(Timer*); 59 | 60 | typedef struct Network 61 | { 62 | int my_socket; 63 | int (*mqttread) (struct Network*, unsigned char*, int, int); 64 | int (*mqttwrite) (struct Network*, unsigned char*, int, int); 65 | } Network; 66 | 67 | int linux_read(Network*, unsigned char*, int, int); 68 | int linux_write(Network*, unsigned char*, int, int); 69 | 70 | DLLExport void NetworkInit(Network*); 71 | DLLExport int NetworkConnect(Network*, char*, int); 72 | DLLExport void NetworkDisconnect(Network*); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /MQTTClient-C/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(mqtt-tests) 2 | 3 | SET(MQTT_TEST_BROKER_HOST "localhost" CACHE STRING "Hostname of a test MQTT broker to use") 4 | SET(MQTT_TEST_PROXY_PORT "1884" CACHE STRING "Port of the test proxy to use") 5 | SET(MQTT_SSL_HOSTNAME "localhost" CACHE STRING "Hostname of a test SSL MQTT broker to use") 6 | SET(CERTDIR $ENV{TRAVIS_BUILD_DIR}/test/ssl) 7 | 8 | ADD_EXECUTABLE( 9 | testc1 10 | test1.c 11 | ) 12 | 13 | target_link_libraries(testc1 paho-embed-mqtt3cc paho-embed-mqtt3c) 14 | target_include_directories(testc1 PRIVATE "../src" "../src/linux") 15 | target_compile_definitions(testc1 PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h) 16 | 17 | ADD_TEST( 18 | NAME testc1 19 | COMMAND "testc1" "--host" ${MQTT_TEST_BROKER_HOST} 20 | ) 21 | -------------------------------------------------------------------------------- /MQTTClient/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | project("paho-mqttclient" C) 18 | 19 | #ADD_SUBDIRECTORY(src) 20 | ADD_SUBDIRECTORY(samples) 21 | ADD_SUBDIRECTORY(test) 22 | -------------------------------------------------------------------------------- /MQTTClient/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | ADD_SUBDIRECTORY(linux) 18 | -------------------------------------------------------------------------------- /MQTTClient/samples/arduino/Hello/Hello.ino: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. and others 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial contribution 15 | * Benjamin Cabe - adapt to IPStack, and add Yun instructions 16 | *******************************************************************************/ 17 | 18 | #define MQTTCLIENT_QOS2 1 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | char printbuf[100]; 27 | 28 | int arrivedcount = 0; 29 | 30 | void messageArrived(MQTT::MessageData& md) 31 | { 32 | MQTT::Message &message = md.message; 33 | 34 | sprintf(printbuf, "Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", 35 | ++arrivedcount, message.qos, message.retained, message.dup, message.id); 36 | Serial.print(printbuf); 37 | sprintf(printbuf, "Payload %s\n", (char*)message.payload); 38 | Serial.print(printbuf); 39 | } 40 | 41 | EthernetClient c; // replace by a YunClient if running on a Yun 42 | IPStack ipstack(c); 43 | MQTT::Client client = MQTT::Client(ipstack); 44 | 45 | byte mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; // replace with your device's MAC 46 | const char* topic = "arduino-sample"; 47 | 48 | void connect() 49 | { 50 | char hostname[] = "iot.eclipse.org"; 51 | int port = 1883; 52 | sprintf(printbuf, "Connecting to %s:%d\n", hostname, port); 53 | Serial.print(printbuf); 54 | int rc = ipstack.connect(hostname, port); 55 | if (rc != 1) 56 | { 57 | sprintf(printbuf, "rc from TCP connect is %d\n", rc); 58 | Serial.print(printbuf); 59 | } 60 | 61 | Serial.println("MQTT connecting"); 62 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 63 | data.MQTTVersion = 3; 64 | data.clientID.cstring = (char*)"arduino-sample"; 65 | rc = client.connect(data); 66 | if (rc != 0) 67 | { 68 | sprintf(printbuf, "rc from MQTT connect is %d\n", rc); 69 | Serial.print(printbuf); 70 | } 71 | Serial.println("MQTT connected"); 72 | 73 | rc = client.subscribe(topic, MQTT::QOS2, messageArrived); 74 | if (rc != 0) 75 | { 76 | sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc); 77 | Serial.print(printbuf); 78 | } 79 | Serial.println("MQTT subscribed"); 80 | } 81 | 82 | void setup() 83 | { 84 | Serial.begin(9600); 85 | Ethernet.begin(mac); // replace by Bridge.begin() if running on a Yun 86 | Serial.println("MQTT Hello example"); 87 | connect(); 88 | } 89 | 90 | void loop() 91 | { 92 | if (!client.isConnected()) 93 | connect(); 94 | 95 | MQTT::Message message; 96 | 97 | arrivedcount = 0; 98 | 99 | // Send and receive QoS 0 message 100 | char buf[100]; 101 | sprintf(buf, "Hello World! QoS 0 message"); 102 | Serial.println(buf); 103 | message.qos = MQTT::QOS0; 104 | message.retained = false; 105 | message.dup = false; 106 | message.payload = (void*)buf; 107 | message.payloadlen = strlen(buf)+1; 108 | int rc = client.publish(topic, message); 109 | while (arrivedcount == 0) 110 | client.yield(1000); 111 | 112 | // Send and receive QoS 1 message 113 | sprintf(buf, "Hello World! QoS 1 message"); 114 | Serial.println(buf); 115 | message.qos = MQTT::QOS1; 116 | message.payloadlen = strlen(buf)+1; 117 | rc = client.publish(topic, message); 118 | while (arrivedcount == 1) 119 | client.yield(1000); 120 | 121 | // Send and receive QoS 2 message 122 | sprintf(buf, "Hello World! QoS 2 message"); 123 | Serial.println(buf); 124 | message.qos = MQTT::QOS2; 125 | message.payloadlen = strlen(buf)+1; 126 | rc = client.publish(topic, message); 127 | while (arrivedcount == 2) 128 | client.yield(1000); 129 | 130 | delay(2000); 131 | } 132 | -------------------------------------------------------------------------------- /MQTTClient/samples/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | # Samples 18 | 19 | add_executable( 20 | hello 21 | hello.cpp 22 | ) 23 | target_include_directories(hello PRIVATE "../../src" "../../src/linux") 24 | target_link_libraries(hello MQTTPacketClient) 25 | 26 | add_executable( 27 | stdoutsub 28 | stdoutsub.cpp 29 | ) 30 | target_include_directories(stdoutsub PRIVATE "../../src" "../../src/linux") 31 | target_link_libraries(stdoutsub paho-embed-mqtt3c) 32 | -------------------------------------------------------------------------------- /MQTTClient/samples/linux/build.sh: -------------------------------------------------------------------------------- 1 | g++ hello.cpp -I ../../src/ -I ../../src/linux -I ../../../MQTTPacket/src ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c -o hello 2 | 3 | g++ -g stdoutsub.cpp -I ../../src -I ../../src/linux -I ../../../MQTTPacket/src ../../../MQTTPacket/src/MQTTFormat.c ../../../MQTTPacket/src/MQTTPacket.c ../../../MQTTPacket/src/MQTTDeserializePublish.c ../../../MQTTPacket/src/MQTTConnectClient.c ../../../MQTTPacket/src/MQTTSubscribeClient.c ../../../MQTTPacket/src/MQTTSerializePublish.c -o stdoutsub ../../../MQTTPacket/src/MQTTConnectServer.c ../../../MQTTPacket/src/MQTTSubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeServer.c ../../../MQTTPacket/src/MQTTUnsubscribeClient.c 4 | -------------------------------------------------------------------------------- /MQTTClient/samples/linux/hello.cpp: -------------------------------------------------------------------------------- 1 | #define MQTTCLIENT_QOS2 1 2 | 3 | #include 4 | 5 | #include "MQTTClient.h" 6 | 7 | #define DEFAULT_STACK_SIZE -1 8 | 9 | #include "linux.cpp" 10 | 11 | int arrivedcount = 0; 12 | 13 | void messageArrived(MQTT::MessageData& md) 14 | { 15 | MQTT::Message &message = md.message; 16 | 17 | printf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", 18 | ++arrivedcount, message.qos, message.retained, message.dup, message.id); 19 | printf("Payload %.*s\n", (int)message.payloadlen, (char*)message.payload); 20 | } 21 | 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | IPStack ipstack = IPStack(); 26 | float version = 0.3; 27 | const char* topic = "mbed-sample"; 28 | 29 | printf("Version is %f\n", version); 30 | 31 | MQTT::Client client = MQTT::Client(ipstack); 32 | 33 | const char* hostname = "iot.eclipse.org"; 34 | int port = 1883; 35 | printf("Connecting to %s:%d\n", hostname, port); 36 | int rc = ipstack.connect(hostname, port); 37 | if (rc != 0) 38 | printf("rc from TCP connect is %d\n", rc); 39 | 40 | printf("MQTT connecting\n"); 41 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 42 | data.MQTTVersion = 3; 43 | data.clientID.cstring = (char*)"mbed-icraggs"; 44 | rc = client.connect(data); 45 | if (rc != 0) 46 | printf("rc from MQTT connect is %d\n", rc); 47 | printf("MQTT connected\n"); 48 | 49 | rc = client.subscribe(topic, MQTT::QOS2, messageArrived); 50 | if (rc != 0) 51 | printf("rc from MQTT subscribe is %d\n", rc); 52 | 53 | MQTT::Message message; 54 | 55 | // QoS 0 56 | char buf[100]; 57 | sprintf(buf, "Hello World! QoS 0 message from app version %f", version); 58 | message.qos = MQTT::QOS0; 59 | message.retained = false; 60 | message.dup = false; 61 | message.payload = (void*)buf; 62 | message.payloadlen = strlen(buf)+1; 63 | rc = client.publish(topic, message); 64 | if (rc != 0) 65 | printf("Error %d from sending QoS 0 message\n", rc); 66 | else while (arrivedcount == 0) 67 | client.yield(100); 68 | 69 | // QoS 1 70 | printf("Now QoS 1\n"); 71 | sprintf(buf, "Hello World! QoS 1 message from app version %f", version); 72 | message.qos = MQTT::QOS1; 73 | message.payloadlen = strlen(buf)+1; 74 | rc = client.publish(topic, message); 75 | if (rc != 0) 76 | printf("Error %d from sending QoS 1 message\n", rc); 77 | else while (arrivedcount == 1) 78 | client.yield(100); 79 | 80 | // QoS 2 81 | sprintf(buf, "Hello World! QoS 2 message from app version %f", version); 82 | message.qos = MQTT::QOS2; 83 | message.payloadlen = strlen(buf)+1; 84 | rc = client.publish(topic, message); 85 | if (rc != 0) 86 | printf("Error %d from sending QoS 2 message\n", rc); 87 | while (arrivedcount == 2) 88 | client.yield(100); 89 | 90 | rc = client.unsubscribe(topic); 91 | if (rc != 0) 92 | printf("rc from unsubscribe was %d\n", rc); 93 | 94 | rc = client.disconnect(); 95 | if (rc != 0) 96 | printf("rc from disconnect was %d\n", rc); 97 | 98 | ipstack.disconnect(); 99 | 100 | printf("Finishing with %d messages received\n", arrivedcount); 101 | 102 | return 0; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /MQTTClient/samples/linux/stdoutsub.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2012, 2013 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial contribution 15 | * Ian Craggs - change delimiter option from char to string 16 | *******************************************************************************/ 17 | 18 | /* 19 | 20 | stdout subscriber 21 | 22 | compulsory parameters: 23 | 24 | topic to subscribe to 25 | 26 | defaulted parameters: 27 | 28 | --host localhost 29 | --port 1883 30 | --qos 2 31 | --delimiter \n 32 | --clientid stdout_subscriber 33 | 34 | --userid none 35 | --password none 36 | 37 | */ 38 | #include 39 | #include 40 | #define MQTT_DEBUG 1 41 | #include "MQTTClient.h" 42 | 43 | #define DEFAULT_STACK_SIZE -1 44 | 45 | #include "linux.cpp" 46 | 47 | #include 48 | #include 49 | #include 50 | 51 | 52 | volatile int toStop = 0; 53 | 54 | 55 | void usage() 56 | { 57 | printf("MQTT stdout subscriber\n"); 58 | printf("Usage: stdoutsub topicname , where options are:\n"); 59 | printf(" --host (default is localhost)\n"); 60 | printf(" --port (default is 1883)\n"); 61 | printf(" --qos (default is 2)\n"); 62 | printf(" --delimiter (default is \\n)\n"); 63 | printf(" --clientid (default is hostname+timestamp)\n"); 64 | printf(" --username none\n"); 65 | printf(" --password none\n"); 66 | printf(" --showtopics (default is on if the topic has a wildcard, else off)\n"); 67 | exit(-1); 68 | } 69 | 70 | 71 | void cfinish(int sig) 72 | { 73 | signal(SIGINT, NULL); 74 | toStop = 1; 75 | } 76 | 77 | 78 | struct opts_struct 79 | { 80 | char* clientid; 81 | int nodelimiter; 82 | char* delimiter; 83 | MQTT::QoS qos; 84 | char* username; 85 | char* password; 86 | char* host; 87 | int port; 88 | int showtopics; 89 | } opts = 90 | { 91 | (char*)"stdout-subscriber", 0, (char*)"\n", MQTT::QOS2, NULL, NULL, (char*)"localhost", 1883, 0 92 | }; 93 | 94 | 95 | void getopts(int argc, char** argv) 96 | { 97 | int count = 2; 98 | 99 | while (count < argc) 100 | { 101 | if (strcmp(argv[count], "--qos") == 0) 102 | { 103 | if (++count < argc) 104 | { 105 | if (strcmp(argv[count], "0") == 0) 106 | opts.qos = MQTT::QOS0; 107 | else if (strcmp(argv[count], "1") == 0) 108 | opts.qos = MQTT::QOS1; 109 | else if (strcmp(argv[count], "2") == 0) 110 | opts.qos = MQTT::QOS2; 111 | else 112 | usage(); 113 | } 114 | else 115 | usage(); 116 | } 117 | else if (strcmp(argv[count], "--host") == 0) 118 | { 119 | if (++count < argc) 120 | opts.host = argv[count]; 121 | else 122 | usage(); 123 | } 124 | else if (strcmp(argv[count], "--port") == 0) 125 | { 126 | if (++count < argc) 127 | opts.port = atoi(argv[count]); 128 | else 129 | usage(); 130 | } 131 | else if (strcmp(argv[count], "--clientid") == 0) 132 | { 133 | if (++count < argc) 134 | opts.clientid = argv[count]; 135 | else 136 | usage(); 137 | } 138 | else if (strcmp(argv[count], "--username") == 0) 139 | { 140 | if (++count < argc) 141 | opts.username = argv[count]; 142 | else 143 | usage(); 144 | } 145 | else if (strcmp(argv[count], "--password") == 0) 146 | { 147 | if (++count < argc) 148 | opts.password = argv[count]; 149 | else 150 | usage(); 151 | } 152 | else if (strcmp(argv[count], "--delimiter") == 0) 153 | { 154 | if (++count < argc) 155 | opts.delimiter = argv[count]; 156 | else 157 | opts.nodelimiter = 1; 158 | } 159 | else if (strcmp(argv[count], "--showtopics") == 0) 160 | { 161 | if (++count < argc) 162 | { 163 | if (strcmp(argv[count], "on") == 0) 164 | opts.showtopics = 1; 165 | else if (strcmp(argv[count], "off") == 0) 166 | opts.showtopics = 0; 167 | else 168 | usage(); 169 | } 170 | else 171 | usage(); 172 | } 173 | count++; 174 | } 175 | 176 | } 177 | 178 | 179 | void myconnect(IPStack& ipstack, MQTT::Client& client, MQTTPacket_connectData& data) 180 | { 181 | printf("Connecting to %s:%d\n", opts.host, opts.port); 182 | int rc = ipstack.connect(opts.host, opts.port); 183 | if (rc != 0) 184 | printf("rc from TCP connect is %d\n", rc); 185 | 186 | rc = client.connect(data); 187 | if (rc != 0) 188 | { 189 | printf("Failed to connect, return code %d\n", rc); 190 | exit(-1); 191 | } 192 | printf("Connected\n"); 193 | } 194 | 195 | 196 | void messageArrived(MQTT::MessageData& md) 197 | { 198 | MQTT::Message &message = md.message; 199 | 200 | if (opts.showtopics) 201 | printf("%.*s\t", md.topicName.lenstring.len, md.topicName.lenstring.data); 202 | if (opts.nodelimiter) 203 | printf("%.*s", (int)message.payloadlen, (char*)message.payload); 204 | else 205 | printf("%.*s%s", (int)message.payloadlen, (char*)message.payload, opts.delimiter); 206 | fflush(stdout); 207 | } 208 | 209 | 210 | int main(int argc, char** argv) 211 | { 212 | int rc = 0; 213 | 214 | if (argc < 2) 215 | usage(); 216 | 217 | char* topic = argv[1]; 218 | 219 | if (strchr(topic, '#') || strchr(topic, '+')) 220 | opts.showtopics = 1; 221 | if (opts.showtopics) 222 | printf("topic is %s\n", topic); 223 | 224 | getopts(argc, argv); 225 | 226 | IPStack ipstack = IPStack(); 227 | MQTT::Client client = MQTT::Client(ipstack); 228 | 229 | signal(SIGINT, cfinish); 230 | signal(SIGTERM, cfinish); 231 | 232 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 233 | data.willFlag = 0; 234 | data.MQTTVersion = 3; 235 | data.clientID.cstring = opts.clientid; 236 | data.username.cstring = opts.username; 237 | data.password.cstring = opts.password; 238 | 239 | data.keepAliveInterval = 10; 240 | data.cleansession = 1; 241 | printf("will flag %d\n", data.willFlag); 242 | 243 | myconnect(ipstack, client, data); 244 | 245 | rc = client.subscribe(topic, opts.qos, messageArrived); 246 | printf("Subscribed %d\n", rc); 247 | 248 | while (!toStop) 249 | { 250 | client.yield(1000); 251 | 252 | //if (!client.isconnected) 253 | // myconnect(ipstack, client, data); 254 | } 255 | 256 | printf("Stopping\n"); 257 | 258 | rc = client.disconnect(); 259 | 260 | ipstack.disconnect(); 261 | 262 | return 0; 263 | } 264 | 265 | 266 | -------------------------------------------------------------------------------- /MQTTClient/src/FP.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2013, 2014 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Sam Grove - initial API and implementation and/or initial documentation 15 | * Ian Craggs - added attached and detached member functions 16 | * Sam Grove - removed need for FP.cpp 17 | *******************************************************************************/ 18 | 19 | #ifndef FP_H 20 | #define FP_H 21 | 22 | /** Example using the FP Class with global functions 23 | * @code 24 | * #include "mbed.h" 25 | * #include "FP.h" 26 | * 27 | * FPfp; 28 | * DigitalOut myled(LED1); 29 | * 30 | * void handler(bool value) 31 | * { 32 | * myled = value; 33 | * return; 34 | * } 35 | * 36 | * int main() 37 | * { 38 | * fp.attach(&handler); 39 | * 40 | * while(1) 41 | * { 42 | * fp(1); 43 | * wait(0.2); 44 | * fp(0); 45 | * wait(0.2); 46 | * } 47 | * } 48 | * @endcode 49 | */ 50 | 51 | /** Example using the FP Class with different class member functions 52 | * @code 53 | * #include "mbed.h" 54 | * #include "FP.h" 55 | * 56 | * FPfp; 57 | * DigitalOut myled(LED4); 58 | * 59 | * class Wrapper 60 | * { 61 | * public: 62 | * Wrapper(){} 63 | * 64 | * void handler(bool value) 65 | * { 66 | * myled = value; 67 | * return; 68 | * } 69 | * }; 70 | * 71 | * int main() 72 | * { 73 | * Wrapper wrapped; 74 | * fp.attach(&wrapped, &Wrapper::handler); 75 | * 76 | * while(1) 77 | * { 78 | * fp(1); 79 | * wait(0.2); 80 | * fp(0); 81 | * wait(0.2); 82 | * } 83 | * } 84 | * @endcode 85 | */ 86 | 87 | /** Example using the FP Class with member FP and member function 88 | * @code 89 | * #include "mbed.h" 90 | * #include "FP.h" 91 | * 92 | * DigitalOut myled(LED2); 93 | * 94 | * class Wrapper 95 | * { 96 | * public: 97 | * Wrapper() 98 | * { 99 | * fp.attach(this, &Wrapper::handler); 100 | * } 101 | * 102 | * void handler(bool value) 103 | * { 104 | * myled = value; 105 | * return; 106 | * } 107 | * 108 | * FPfp; 109 | * }; 110 | * 111 | * int main() 112 | * { 113 | * Wrapper wrapped; 114 | * 115 | * while(1) 116 | * { 117 | * wrapped.fp(1); 118 | * wait(0.2); 119 | * wrapped.fp(0); 120 | * wait(0.2); 121 | * } 122 | * } 123 | * @endcode 124 | */ 125 | 126 | /** 127 | * @class FP 128 | * @brief API for managing Function Pointers 129 | */ 130 | template 131 | class FP 132 | { 133 | public: 134 | /** Create the FP object - only one callback can be attached to the object, that is 135 | * a member function or a global function, not both at the same time 136 | */ 137 | FP() 138 | { 139 | obj_callback = 0; 140 | c_callback = 0; 141 | } 142 | 143 | /** Add a callback function to the object 144 | * @param item - Address of the initialized object 145 | * @param member - Address of the member function (dont forget the scope that the function is defined in) 146 | */ 147 | template 148 | void attach(T *item, retT (T::*method)(argT)) 149 | { 150 | obj_callback = (FPtrDummy *)(item); 151 | method_callback = (retT (FPtrDummy::*)(argT))(method); 152 | return; 153 | } 154 | 155 | /** Add a callback function to the object 156 | * @param function - The address of a globally defined function 157 | */ 158 | void attach(retT (*function)(argT)) 159 | { 160 | c_callback = function; 161 | } 162 | 163 | /** Invoke the function attached to the class 164 | * @param arg - An argument that is passed into the function handler that is called 165 | * @return The return from the function hanlder called by this class 166 | */ 167 | retT operator()(argT arg) const 168 | { 169 | if( 0 != c_callback ) { 170 | return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg); 171 | } 172 | return (retT)0; 173 | } 174 | 175 | /** Determine if an callback is currently hooked 176 | * @return 1 if a method is hooked, 0 otherwise 177 | */ 178 | bool attached() 179 | { 180 | return obj_callback || c_callback; 181 | } 182 | 183 | /** Release a function from the callback hook 184 | */ 185 | void detach() 186 | { 187 | obj_callback = 0; 188 | c_callback = 0; 189 | } 190 | 191 | private: 192 | 193 | // empty type used for casting 194 | class FPtrDummy; 195 | 196 | FPtrDummy *obj_callback; 197 | 198 | /** 199 | * @union Funciton 200 | * @brief Member or global callback function 201 | */ 202 | union { 203 | retT (*c_callback)(argT); /*!< Footprint for a global function */ 204 | retT (FPtrDummy::*method_callback)(argT); /*!< Footprint for a member function */ 205 | }; 206 | }; 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /MQTTClient/src/MQTTLogging.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #if !defined(MQTT_LOGGING_H) 18 | #define MQTT_LOGGING_H 19 | 20 | #define STREAM stdout 21 | #if !defined(DEBUG) 22 | #define DEBUG(...) \ 23 | {\ 24 | fprintf(STREAM, "DEBUG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \ 25 | fprintf(STREAM, ##__VA_ARGS__); \ 26 | fflush(STREAM); \ 27 | } 28 | #endif 29 | #if !defined(LOG) 30 | #define LOG(...) \ 31 | {\ 32 | fprintf(STREAM, "LOG: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \ 33 | fprintf(STREAM, ##__VA_ARGS__); \ 34 | fflush(STREAM); \ 35 | } 36 | #endif 37 | #if !defined(WARN) 38 | #define WARN(...) \ 39 | { \ 40 | fprintf(STREAM, "WARN: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \ 41 | fprintf(STREAM, ##__VA_ARGS__); \ 42 | fflush(STREAM); \ 43 | } 44 | #endif 45 | #if !defined(ERROR) 46 | #define ERROR(...) \ 47 | { \ 48 | fprintf(STREAM, "ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \ 49 | fprintf(STREAM, ##__VA_ARGS__); \ 50 | fflush(STREAM); \ 51 | exit(1); \ 52 | } 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /MQTTClient/src/arduino/Countdown.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #if !defined(COUNTDOWN_H) 18 | #define COUNTDOWN_H 19 | 20 | class Countdown 21 | { 22 | public: 23 | Countdown() 24 | { 25 | interval_end_ms = 0L; 26 | } 27 | 28 | Countdown(int ms) 29 | { 30 | countdown_ms(ms); 31 | } 32 | 33 | bool expired() 34 | { 35 | return (interval_end_ms > 0L) && (millis() >= interval_end_ms); 36 | } 37 | 38 | void countdown_ms(unsigned long ms) 39 | { 40 | interval_end_ms = millis() + ms; 41 | } 42 | 43 | void countdown(int seconds) 44 | { 45 | countdown_ms((unsigned long)seconds * 1000L); 46 | } 47 | 48 | int left_ms() 49 | { 50 | return interval_end_ms - millis(); 51 | } 52 | 53 | private: 54 | unsigned long interval_end_ms; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /MQTTClient/src/arduino/IPStack.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2017 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Benjamin Cabe - generic IPStack 16 | *******************************************************************************/ 17 | 18 | #if !defined(IPSTACK_H) 19 | #define IPSTACK_H 20 | 21 | #ifndef WiFi_h 22 | #include 23 | #endif 24 | 25 | #include 26 | 27 | class IPStack 28 | { 29 | public: 30 | IPStack(Client& client) : client(&client) 31 | { 32 | 33 | } 34 | 35 | int connect(char* hostname, int port) 36 | { 37 | return client->connect(hostname, port); 38 | } 39 | 40 | int connect(uint32_t hostname, int port) 41 | { 42 | return client->connect(hostname, port); 43 | } 44 | 45 | int read(unsigned char* buffer, int len, int timeout) 46 | { 47 | int interval = 10; // all times are in milliseconds 48 | int total = 0, rc = -1; 49 | 50 | if (timeout < 30) 51 | interval = 2; 52 | while (client->available() < len && total < timeout) 53 | { 54 | delay(interval); 55 | total += interval; 56 | } 57 | if (client->available() >= len) 58 | rc = client->readBytes((char*)buffer, len); 59 | return rc; 60 | } 61 | 62 | int write(unsigned char* buffer, int len, int timeout) 63 | { 64 | client->setTimeout(timeout); 65 | return client->write((uint8_t*)buffer, len); 66 | } 67 | 68 | int disconnect() 69 | { 70 | client->stop(); 71 | return 0; 72 | } 73 | 74 | private: 75 | 76 | Client* client; 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /MQTTClient/src/arduino/WifiIPStack.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #ifndef ARDUINOWIFIIPSTACK_H 18 | #define ARDUINOWIFIIPSTACK_H 19 | 20 | #include 21 | 22 | class WifiIPStack 23 | { 24 | public: 25 | WifiIPStack() 26 | { 27 | //WiFi.begin(); // Use DHCP 28 | iface.setTimeout(1000); // 1 second Timeout 29 | } 30 | 31 | int connect(char* hostname, int port) 32 | { 33 | return iface.connect(hostname, port); 34 | } 35 | 36 | int connect(uint32_t hostname, int port) 37 | { 38 | return iface.connect(hostname, port); 39 | } 40 | 41 | int read(char* buffer, int len, int timeout) 42 | { 43 | iface.setTimeout(timeout); 44 | while(!iface.available()); 45 | return iface.readBytes(buffer, len); 46 | } 47 | 48 | int write(char* buffer, int len, int timeout) 49 | { 50 | iface.setTimeout(timeout); 51 | return iface.write((uint8_t*)buffer, len); 52 | } 53 | 54 | int disconnect() 55 | { 56 | iface.stop(); 57 | return 0; 58 | } 59 | 60 | private: 61 | 62 | WiFiClient iface; 63 | 64 | }; 65 | 66 | #endif 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /MQTTClient/src/linux/linux.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2023 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - ensure read returns if no bytes read 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | 37 | class IPStack 38 | { 39 | public: 40 | IPStack() 41 | { 42 | signal(SIGPIPE, SIG_IGN); 43 | } 44 | 45 | int connect(const char* hostname, int port) 46 | { 47 | int type = SOCK_STREAM; 48 | struct sockaddr_in address; 49 | int rc = -1; 50 | sa_family_t family = AF_INET; 51 | struct addrinfo *result = NULL; 52 | struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL}; 53 | 54 | if ((rc = getaddrinfo(hostname, NULL, &hints, &result)) == 0) 55 | { 56 | struct addrinfo* res = result; 57 | 58 | /* prefer ip4 addresses */ 59 | while (res) 60 | { 61 | if (res->ai_family == AF_INET) 62 | { 63 | result = res; 64 | break; 65 | } 66 | res = res->ai_next; 67 | } 68 | 69 | if (result->ai_family == AF_INET) 70 | { 71 | address.sin_port = htons(port); 72 | address.sin_family = family = AF_INET; 73 | address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr; 74 | } 75 | else 76 | rc = -1; 77 | 78 | freeaddrinfo(result); 79 | } 80 | 81 | if (rc == 0) 82 | { 83 | mysock = socket(family, type, 0); 84 | if (mysock != -1) 85 | { 86 | int opt = 1; 87 | 88 | //if (setsockopt(mysock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0) 89 | // printf("Could not set SO_NOSIGPIPE for socket %d", mysock); 90 | 91 | rc = ::connect(mysock, (struct sockaddr*)&address, sizeof(address)); 92 | } 93 | } 94 | 95 | return rc; 96 | } 97 | 98 | // return -1 on error, or the number of bytes read 99 | // which could be 0 on a read timeout 100 | int read(unsigned char* buffer, int len, int timeout_ms) 101 | { 102 | struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000}; 103 | if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0)) 104 | { 105 | interval.tv_sec = 0; 106 | interval.tv_usec = 100; 107 | } 108 | 109 | setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval)); 110 | 111 | int bytes = 0; 112 | int i = 0; const int max_tries = 10; 113 | while (bytes < len) 114 | { 115 | int rc = ::recv(mysock, &buffer[bytes], (size_t)(len - bytes), 0); 116 | if (rc == -1) 117 | { 118 | if (errno != EAGAIN && errno != EWOULDBLOCK) 119 | bytes = -1; 120 | break; 121 | } 122 | else 123 | bytes += rc; 124 | if (++i >= max_tries) 125 | break; 126 | if (rc == 0) 127 | break; 128 | } 129 | return bytes; 130 | } 131 | 132 | int write(unsigned char* buffer, int len, int timeout) 133 | { 134 | struct timeval tv; 135 | 136 | tv.tv_sec = 0; /* 30 Secs Timeout */ 137 | tv.tv_usec = timeout * 1000; // Not init'ing this can cause strange errors 138 | 139 | setsockopt(mysock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv,sizeof(struct timeval)); 140 | int rc = ::write(mysock, buffer, len); 141 | //printf("write rc %d\n", rc); 142 | return rc; 143 | } 144 | 145 | int disconnect() 146 | { 147 | return ::close(mysock); 148 | } 149 | 150 | private: 151 | 152 | int mysock; 153 | }; 154 | 155 | 156 | class Countdown 157 | { 158 | public: 159 | Countdown() 160 | { 161 | 162 | } 163 | 164 | Countdown(int ms) 165 | { 166 | countdown_ms(ms); 167 | } 168 | 169 | 170 | bool expired() 171 | { 172 | struct timeval now, res; 173 | gettimeofday(&now, NULL); 174 | timersub(&end_time, &now, &res); 175 | //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); 176 | //if (res.tv_sec > 0 || res.tv_usec > 0) 177 | // printf("expired %d %d\n", res.tv_sec, res.tv_usec); 178 | return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); 179 | } 180 | 181 | 182 | void countdown_ms(int ms) 183 | { 184 | struct timeval now; 185 | gettimeofday(&now, NULL); 186 | struct timeval interval = {ms / 1000, (ms % 1000) * 1000}; 187 | //printf("interval %d %d\n", interval.tv_sec, interval.tv_usec); 188 | timeradd(&now, &interval, &end_time); 189 | } 190 | 191 | 192 | void countdown(int seconds) 193 | { 194 | struct timeval now; 195 | gettimeofday(&now, NULL); 196 | struct timeval interval = {seconds, 0}; 197 | timeradd(&now, &interval, &end_time); 198 | } 199 | 200 | 201 | int left_ms() 202 | { 203 | struct timeval now, res; 204 | gettimeofday(&now, NULL); 205 | timersub(&end_time, &now, &res); 206 | //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); 207 | return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000; 208 | } 209 | 210 | private: 211 | 212 | struct timeval end_time; 213 | }; 214 | -------------------------------------------------------------------------------- /MQTTClient/src/mbed/MQTTEthernet.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(MQTTETHERNET_H) 3 | #define MQTTETHERNET_H 4 | 5 | #include "MQTTmbed.h" 6 | #include "EthernetInterface.h" 7 | #include "MQTTSocket.h" 8 | 9 | class MQTTEthernet : public MQTTSocket 10 | { 11 | public: 12 | MQTTEthernet() : MQTTSocket(ð) 13 | { 14 | eth.connect(); 15 | } 16 | 17 | EthernetInterface& getEth() 18 | { 19 | return eth; 20 | } 21 | 22 | private: 23 | 24 | EthernetInterface eth; 25 | 26 | }; 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /MQTTClient/src/mbed/MQTTSocket.h: -------------------------------------------------------------------------------- 1 | #if !defined(MQTTSOCKET_H) 2 | #define MQTTSOCKET_H 3 | 4 | #include "MQTTmbed.h" 5 | #include 6 | #include 7 | 8 | class MQTTSocket 9 | { 10 | public: 11 | MQTTSocket(EthernetInterface *anet) 12 | { 13 | net = anet; 14 | open = false; 15 | } 16 | 17 | int connect(char* hostname, int port, int timeout=1000) 18 | { 19 | if (open) 20 | disconnect(); 21 | nsapi_error_t rc = mysock.open(net); 22 | open = true; 23 | mysock.set_blocking(true); 24 | mysock.set_timeout((unsigned int)timeout); 25 | rc = mysock.connect(hostname, port); 26 | mysock.set_blocking(false); // blocking timeouts seem not to work 27 | return rc; 28 | } 29 | 30 | // common read/write routine, avoiding blocking timeouts 31 | int common(unsigned char* buffer, int len, int timeout, bool read) 32 | { 33 | timer.start(); 34 | mysock.set_blocking(false); // blocking timeouts seem not to work 35 | int bytes = 0; 36 | bool first = true; 37 | do 38 | { 39 | if (first) 40 | first = false; 41 | else 42 | wait_ms(timeout < 100 ? timeout : 100); 43 | int rc; 44 | if (read) 45 | rc = mysock.recv((char*)buffer, len); 46 | else 47 | rc = mysock.send((char*)buffer, len); 48 | if (rc < 0) 49 | { 50 | if (rc != NSAPI_ERROR_WOULD_BLOCK) 51 | { 52 | bytes = -1; 53 | break; 54 | } 55 | } 56 | else 57 | bytes += rc; 58 | } 59 | while (bytes < len && timer.read_ms() < timeout); 60 | timer.stop(); 61 | return bytes; 62 | } 63 | 64 | /* returns the number of bytes read, which could be 0. 65 | -1 if there was an error on the socket 66 | */ 67 | int read(unsigned char* buffer, int len, int timeout) 68 | { 69 | return common(buffer, len, timeout, true); 70 | } 71 | 72 | int write(unsigned char* buffer, int len, int timeout) 73 | { 74 | return common(buffer, len, timeout, false); 75 | } 76 | 77 | int disconnect() 78 | { 79 | open = false; 80 | return mysock.close(); 81 | } 82 | 83 | /*bool is_connected() 84 | { 85 | return mysock.is_connected(); 86 | }*/ 87 | 88 | private: 89 | 90 | bool open; 91 | TCPSocket mysock; 92 | EthernetInterface *net; 93 | Timer timer; 94 | 95 | }; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /MQTTClient/src/mbed/MQTTmbed.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2017 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - change Timer member initialization to avoid copy constructor 16 | *******************************************************************************/ 17 | 18 | #if !defined(MQTT_MBED_H) 19 | #define MQTT_MBED_H 20 | 21 | #include "mbed.h" 22 | 23 | class Countdown 24 | { 25 | public: 26 | Countdown() : t() 27 | { 28 | 29 | } 30 | 31 | Countdown(int ms) : t() 32 | { 33 | countdown_ms(ms); 34 | } 35 | 36 | 37 | bool expired() 38 | { 39 | return t.read_ms() >= interval_end_ms; 40 | } 41 | 42 | void countdown_ms(unsigned long ms) 43 | { 44 | t.stop(); 45 | interval_end_ms = ms; 46 | t.reset(); 47 | t.start(); 48 | } 49 | 50 | void countdown(int seconds) 51 | { 52 | countdown_ms((unsigned long)seconds * 1000L); 53 | } 54 | 55 | int left_ms() 56 | { 57 | return interval_end_ms - t.read_ms(); 58 | } 59 | 60 | private: 61 | Timer t; 62 | unsigned long interval_end_ms; 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /MQTTClient/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(mqttcpp-tests) 2 | 3 | SET(MQTT_TEST_BROKER_HOST "localhost" CACHE STRING "Hostname of a test MQTT broker to use") 4 | SET(MQTT_TEST_PROXY_PORT "1884" CACHE STRING "Port of the test proxy to use") 5 | SET(MQTT_SSL_HOSTNAME "localhost" CACHE STRING "Hostname of a test SSL MQTT broker to use") 6 | SET(CERTDIR $ENV{TRAVIS_BUILD_DIR}/test/ssl) 7 | 8 | ADD_EXECUTABLE( 9 | testcpp1 10 | test1.cpp 11 | ) 12 | 13 | target_compile_definitions(testcpp1 PRIVATE MQTTCLIENT_QOS1=1 MQTTCLIENT_QOS2=1) 14 | target_include_directories(testcpp1 PRIVATE "../src" "../src/linux") 15 | target_link_libraries(testcpp1 MQTTPacketClient MQTTPacketServer) 16 | 17 | ADD_TEST( 18 | NAME testcpp1 19 | COMMAND "testcpp1" "--host" ${MQTT_TEST_BROKER_HOST} 20 | ) 21 | -------------------------------------------------------------------------------- /MQTTPacket/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | project("paho-mqttpacket" C) 18 | 19 | ADD_SUBDIRECTORY(src) 20 | ADD_SUBDIRECTORY(samples) 21 | ADD_SUBDIRECTORY(test) 22 | -------------------------------------------------------------------------------- /MQTTPacket/samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | # Samples 18 | 19 | include_directories(../src) 20 | 21 | add_executable( 22 | pub0sub1 23 | pub0sub1.c transport.c 24 | ) 25 | target_link_libraries(pub0sub1 paho-embed-mqtt3c) 26 | 27 | add_executable( 28 | pub0sub1_nb 29 | pub0sub1_nb.c transport.c 30 | ) 31 | target_link_libraries(pub0sub1_nb paho-embed-mqtt3c) 32 | 33 | add_executable( 34 | qos0pub 35 | qos0pub.c transport.c 36 | ) 37 | target_link_libraries(qos0pub paho-embed-mqtt3c) 38 | -------------------------------------------------------------------------------- /MQTTPacket/samples/baremetalserial/build: -------------------------------------------------------------------------------- 1 | gcc -g -Wall pub0sub1_nb.c transport.c -I ../../src ../../src/MQTTConnectClient.c ../../src/MQTTSerializePublish.c ../../src/MQTTPacket.c ../../src/MQTTSubscribeClient.c -o pub0sub1_nb ../../src/MQTTDeserializePublish.c ../../src/MQTTConnectServer.c ../../src/MQTTSubscribeServer.c ../../src/MQTTUnsubscribeServer.c ../../src/MQTTUnsubscribeClient.c 2 | gcc -g -Wall ping_nb.c transport.c -I ../../src ../../src/MQTTConnectClient.c ../../src/MQTTPacket.c -o ping_nb 3 | 4 | -------------------------------------------------------------------------------- /MQTTPacket/samples/baremetalserial/transport.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - port to the bare metal environment and serial media specifics 16 | *******************************************************************************/ 17 | 18 | /** By the way, this is a nice bare bones example, easier to expand to whatever non-OS 19 | media you might have */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "transport.h" 27 | 28 | /** 29 | This simple low-level implementation assumes a single connection for a single thread. Thus, single static 30 | variables are used for that connection. 31 | On other scenarios, you might want to put all these variables into a structure and index via the 'sock' 32 | parameter, as some functions show in the comments 33 | The blocking rx function is not supported. 34 | If you plan on writing one, take into account that the current implementation of 35 | MQTTPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions 36 | to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int) 37 | */ 38 | static transport_iofunctions_t *io = NULL; 39 | static unsigned char *from = NULL; // to keep track of data sending 40 | static int howmany; // ditto 41 | 42 | 43 | void transport_sendPacketBuffernb_start(int sock, unsigned char* buf, int buflen) 44 | { 45 | from = buf; // from[sock] or mystruct[sock].from 46 | howmany = buflen; // myhowmany[sock] or mystruct[sock].howmany 47 | } 48 | 49 | int transport_sendPacketBuffernb(int sock) 50 | { 51 | transport_iofunctions_t *myio = io; // io[sock] or mystruct[sock].io 52 | int len; 53 | 54 | /* you should have called open() with a valid pointer to a valid struct and 55 | called sendPacketBuffernb_start with a valid buffer, before calling this */ 56 | assert((myio != NULL) && (myio->send != NULL) && (from != NULL)); 57 | if((len = myio->send(from, howmany)) > 0){ 58 | from += len; 59 | if((howmany -= len) <= 0){ 60 | return TRANSPORT_DONE; 61 | } 62 | } else if(len < 0){ 63 | return TRANSPORT_ERROR; 64 | } 65 | return TRANSPORT_AGAIN; 66 | } 67 | 68 | int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen) 69 | { 70 | int rc; 71 | 72 | transport_sendPacketBuffernb_start(sock, buf, buflen); 73 | while((rc=transport_sendPacketBuffernb(sock)) == TRANSPORT_AGAIN){ 74 | /* this is unlikely to loop forever unless there is a hardware problem */ 75 | } 76 | if(rc == TRANSPORT_DONE){ 77 | return buflen; 78 | } 79 | return TRANSPORT_ERROR; 80 | } 81 | 82 | 83 | int transport_getdata(unsigned char* buf, int count) 84 | { 85 | assert(0); /* This function is NOT supported, it is just here to tease you */ 86 | return TRANSPORT_ERROR; /* nah, it is here for similarity with other transport examples */ 87 | } 88 | 89 | int transport_getdatanb(void *sck, unsigned char* buf, int count) 90 | { 91 | //int sock = *((int *)sck); /* sck: pointer to whatever the system may use to identify the transport */ 92 | transport_iofunctions_t *myio = io; // io[sock] or mystruct[sock].io 93 | int len; 94 | 95 | /* you should have called open() with a valid pointer to a valid struct before calling this */ 96 | assert((myio != NULL) && (myio->recv != NULL)); 97 | /* this call will return immediately if no bytes, or return whatever outstanding bytes we have, 98 | upto count */ 99 | if((len = myio->recv(buf, count)) >= 0) 100 | return len; 101 | return TRANSPORT_ERROR; 102 | } 103 | 104 | /** 105 | return >=0 for a connection descriptor, <0 for an error code 106 | */ 107 | int transport_open(transport_iofunctions_t *thisio) 108 | { 109 | int idx=0; // for multiple connections, you might, basically turn myio into myio[MAX_CONNECTIONS], 110 | 111 | //if((idx=assignidx()) >= MAX_CONNECTIONS) // somehow assign an index, 112 | // return TRANSPORT_ERROR; 113 | io = thisio; // store myio[idx] = thisio, or mystruct[idx].io = thisio, 114 | return idx; // and return the index used 115 | } 116 | 117 | int transport_close(int sock) 118 | { 119 | int rc=TRANSPORT_DONE; 120 | 121 | return rc; 122 | } 123 | -------------------------------------------------------------------------------- /MQTTPacket/samples/baremetalserial/transport.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - media specifics, nice api doc :^) 16 | *******************************************************************************/ 17 | 18 | typedef struct { 19 | int (*send)(unsigned char *address, unsigned int bytes); ///< pointer to function to send 'bytes' bytes, returns the actual number of bytes sent 20 | int (*recv)(unsigned char *address, unsigned int maxbytes); ///< pointer to function to receive upto 'maxbytes' bytes, returns the actual number of bytes copied 21 | } transport_iofunctions_t; 22 | 23 | #define TRANSPORT_DONE 1 24 | #define TRANSPORT_AGAIN 0 25 | #define TRANSPORT_ERROR -1 26 | /** 27 | @note Blocks until requested buflen is sent 28 | */ 29 | int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen); 30 | /** 31 | @note Blocks until requested count is received, as MQTTPacket_read() expects 32 | @warning This function is not supported (not implemented) 33 | @warning unless you provide a timeout, this function can block forever. Socket based systems do have 34 | a built in timeout, if your system can provide this, do modify this function, otherwise use getdatanb() instead 35 | @returns number of bytes read 36 | */ 37 | int transport_getdata(unsigned char* buf, int count); 38 | 39 | /** 40 | This is a bare metal implementation, so we must have non-blocking functions, 41 | the process of pumping to serial lines can result a bit slow and we don't want to busy wait. 42 | This function starts the process, you will call sendPacketBuffernb() until it reports success (or error) 43 | */ 44 | void transport_sendPacketBuffernb_start(int sock, unsigned char* buf, int buflen); 45 | /** 46 | This is a bare metal implementation, so we must have non-blocking functions, 47 | the process of pumping to serial lines can result a bit slow and we don't want to busy wait 48 | @returns TRANSPORT_DONE if finished, TRANSPORT_AGAIN for call again, or TRANSPORT_ERROR on error 49 | @note you will call again until it finishes (this is stream) 50 | */ 51 | int transport_sendPacketBuffernb(int sock); 52 | 53 | /** 54 | This is a bare metal implementation, so we must have non-blocking functions, 55 | the process of sucking from serial lines can result a bit slow and we don't want to busy wait 56 | @return the actual number of bytes read, 0 for none, or TRANSPORT_ERROR on error 57 | @note you will call again until total number of expected bytes is read (this is stream) 58 | */ 59 | int transport_getdatanb(void *sck, unsigned char* buf, int count); 60 | 61 | /** 62 | We assume whatever connection needs to be done, it is externally established by the specifics of the hardware 63 | E.g.: 64 | A cell modem: you will call AT+whatever and put the modem in transparent mode, OR, you will embed 65 | the AT+xSENDx / AT+xRECVx commands into the former sendPacketBuffer() and getdatanb() functions 66 | @param thisio pointer to a structure containing all necessary stuff to handle direct serial I/O 67 | @returns whatever indicator the system assigns to this link, if any. (a.k.a. : 'sock'), or TRANSPORT_ERROR for error 68 | */ 69 | int transport_open(transport_iofunctions_t *thisio); 70 | int transport_close(int sock); 71 | -------------------------------------------------------------------------------- /MQTTPacket/samples/build: -------------------------------------------------------------------------------- 1 | gcc -Wall -c transport.c -Os -s 2 | gcc qos0pub.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c -o qos0pub -Os -s 3 | 4 | gcc pub0sub1.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c ../src/MQTTSubscribeClient.c -o pub0sub1 ../src/MQTTDeserializePublish.c -Os -s ../src/MQTTConnectServer.c ../src/MQTTSubscribeServer.c ../src/MQTTUnsubscribeServer.c ../src/MQTTUnsubscribeClient.c -ggdb 5 | gcc pub0sub1_nb.c transport.o -I ../src ../src/MQTTConnectClient.c ../src/MQTTSerializePublish.c ../src/MQTTPacket.c ../src/MQTTSubscribeClient.c -o pub0sub1_nb ../src/MQTTDeserializePublish.c -Os -s ../src/MQTTConnectServer.c ../src/MQTTSubscribeServer.c ../src/MQTTUnsubscribeServer.c ../src/MQTTUnsubscribeClient.c -ggdb 6 | 7 | -------------------------------------------------------------------------------- /MQTTPacket/samples/null.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char** argv) 2 | { 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /MQTTPacket/samples/ping.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - port 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "MQTTPacket.h" 23 | #include "transport.h" 24 | 25 | #define KEEPALIVE_INTERVAL 20 26 | 27 | /* This is to get a timebase in seconds to test the sample */ 28 | #include 29 | time_t old_t; 30 | void start_ping_timer(void) 31 | { 32 | time(&old_t); 33 | old_t += KEEPALIVE_INTERVAL/2 + 1; 34 | } 35 | 36 | int time_to_ping(void) 37 | { 38 | time_t t; 39 | 40 | time(&t); 41 | if(t >= old_t) 42 | return 1; 43 | return 0; 44 | } 45 | 46 | /* This is in order to get an asynchronous signal to stop the sample, 47 | as the code loops waiting for msgs on the subscribed topic. 48 | Your actual code will depend on your hw and approach*/ 49 | #include 50 | 51 | int toStop = 0; 52 | 53 | void cfinish(int sig) 54 | { 55 | signal(SIGINT, NULL); 56 | toStop = 1; 57 | } 58 | 59 | void stop_init(void) 60 | { 61 | signal(SIGINT, cfinish); 62 | signal(SIGTERM, cfinish); 63 | } 64 | /* */ 65 | 66 | int main(int argc, char *argv[]) 67 | { 68 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 69 | int rc = 0; 70 | int mysock = 0; 71 | unsigned char buf[200]; 72 | int buflen = sizeof(buf); 73 | int len = 0; 74 | char *host = "m2m.eclipse.org"; 75 | int port = 1883; 76 | 77 | stop_init(); 78 | if (argc > 1) 79 | host = argv[1]; 80 | 81 | if (argc > 2) 82 | port = atoi(argv[2]); 83 | 84 | mysock = transport_open(host, port); 85 | if(mysock < 0) 86 | return mysock; 87 | 88 | printf("Sending to hostname %s port %d\n", host, port); 89 | 90 | data.clientID.cstring = "me"; 91 | data.keepAliveInterval = KEEPALIVE_INTERVAL; 92 | data.cleansession = 1; 93 | data.username.cstring = "testuser"; 94 | data.password.cstring = "testpassword"; 95 | 96 | len = MQTTSerialize_connect(buf, buflen, &data); 97 | rc = transport_sendPacketBuffer(mysock, buf, len); 98 | 99 | printf("Sent MQTT connect\n"); 100 | /* wait for connack */ 101 | if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK) 102 | { 103 | unsigned char sessionPresent, connack_rc; 104 | 105 | if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0) 106 | { 107 | printf("Unable to connect, return code %d\n", connack_rc); 108 | goto exit; 109 | } 110 | } 111 | else 112 | goto exit; 113 | 114 | printf("MQTT connected\n"); 115 | start_ping_timer(); 116 | 117 | while (!toStop) 118 | { 119 | while(!time_to_ping()); 120 | len = MQTTSerialize_pingreq(buf, buflen); 121 | transport_sendPacketBuffer(mysock, buf, len); 122 | printf("Ping..."); 123 | if (MQTTPacket_read(buf, buflen, transport_getdata) == PINGRESP){ 124 | printf("Pong\n"); 125 | start_ping_timer(); 126 | } 127 | else { 128 | printf("OOPS\n"); 129 | goto exit; 130 | } 131 | 132 | } 133 | 134 | printf("disconnecting\n"); 135 | len = MQTTSerialize_disconnect(buf, buflen); 136 | rc = transport_sendPacketBuffer(mysock, buf, len); 137 | 138 | exit: 139 | transport_close(mysock); 140 | 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /MQTTPacket/samples/ping_nb.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - port and nonblocking 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "MQTTPacket.h" 23 | #include "transport.h" 24 | 25 | #define KEEPALIVE_INTERVAL 20 26 | 27 | /* This is to get a timebase in seconds to test the sample */ 28 | #include 29 | time_t old_t; 30 | void start_ping_timer(void) 31 | { 32 | time(&old_t); 33 | old_t += KEEPALIVE_INTERVAL/2 + 1; 34 | } 35 | 36 | int time_to_ping(void) 37 | { 38 | time_t t; 39 | 40 | time(&t); 41 | if(t >= old_t) 42 | return 1; 43 | return 0; 44 | } 45 | 46 | /* This is in order to get an asynchronous signal to stop the sample, 47 | as the code loops waiting for msgs on the subscribed topic. 48 | Your actual code will depend on your hw and approach*/ 49 | #include 50 | 51 | int toStop = 0; 52 | 53 | void cfinish(int sig) 54 | { 55 | signal(SIGINT, NULL); 56 | toStop = 1; 57 | } 58 | 59 | void stop_init(void) 60 | { 61 | signal(SIGINT, cfinish); 62 | signal(SIGTERM, cfinish); 63 | } 64 | /* */ 65 | 66 | enum states { IDLE, GETPONG }; 67 | 68 | int main(int argc, char *argv[]) 69 | { 70 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 71 | int rc = 0; 72 | int mysock = 0; 73 | unsigned char buf[200]; 74 | int buflen = sizeof(buf); 75 | int len = 0; 76 | char *host = "m2m.eclipse.org"; 77 | int port = 1883; 78 | MQTTTransport mytransport; 79 | int state; 80 | 81 | stop_init(); 82 | if (argc > 1) 83 | host = argv[1]; 84 | 85 | if (argc > 2) 86 | port = atoi(argv[2]); 87 | 88 | mysock = transport_open(host, port); 89 | if(mysock < 0) 90 | return mysock; 91 | 92 | printf("Sending to hostname %s port %d\n", host, port); 93 | 94 | mytransport.sck = &mysock; 95 | mytransport.getfn = transport_getdatanb; 96 | mytransport.state = 0; 97 | data.clientID.cstring = "me"; 98 | data.keepAliveInterval = KEEPALIVE_INTERVAL; 99 | data.cleansession = 1; 100 | data.username.cstring = "testuser"; 101 | data.password.cstring = "testpassword"; 102 | 103 | len = MQTTSerialize_connect(buf, buflen, &data); 104 | rc = transport_sendPacketBuffer(mysock, buf, len); 105 | 106 | printf("Sent MQTT connect\n"); 107 | /* wait for connack */ 108 | do { 109 | int frc; 110 | if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == CONNACK){ 111 | unsigned char sessionPresent, connack_rc; 112 | if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0){ 113 | printf("Unable to connect, return code %d\n", connack_rc); 114 | goto exit; 115 | } 116 | break; 117 | } 118 | else if (frc == -1) 119 | goto exit; 120 | } while (1); /* handle timeouts here */ 121 | 122 | printf("MQTT connected\n"); 123 | start_ping_timer(); 124 | 125 | state = IDLE; 126 | while (!toStop) { 127 | switch(state){ 128 | case IDLE: 129 | if(time_to_ping()){ 130 | len = MQTTSerialize_pingreq(buf, buflen); 131 | transport_sendPacketBuffer(mysock, buf, len); 132 | printf("Ping..."); 133 | state = GETPONG; 134 | } 135 | break; 136 | case GETPONG: 137 | if((rc=MQTTPacket_readnb(buf, buflen, &mytransport)) == PINGRESP){ 138 | printf("Pong\n"); 139 | start_ping_timer(); 140 | state = IDLE; 141 | } else if(rc == -1){ 142 | printf("OOPS\n"); 143 | goto exit; 144 | } 145 | break; 146 | } 147 | } 148 | 149 | printf("disconnecting\n"); 150 | len = MQTTSerialize_disconnect(buf, buflen); 151 | rc = transport_sendPacketBuffer(mysock, buf, len); 152 | 153 | exit: 154 | transport_close(mysock); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /MQTTPacket/samples/pub0sub1.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - clarifications and/or documentation extension 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "MQTTPacket.h" 23 | #include "transport.h" 24 | 25 | /* This is in order to get an asynchronous signal to stop the sample, 26 | as the code loops waiting for msgs on the subscribed topic. 27 | Your actual code will depend on your hw and approach*/ 28 | #include 29 | 30 | int toStop = 0; 31 | 32 | void cfinish(int sig) 33 | { 34 | signal(SIGINT, NULL); 35 | toStop = 1; 36 | } 37 | 38 | void stop_init(void) 39 | { 40 | signal(SIGINT, cfinish); 41 | signal(SIGTERM, cfinish); 42 | } 43 | /* */ 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 48 | int rc = 0; 49 | int mysock = 0; 50 | unsigned char buf[200]; 51 | int buflen = sizeof(buf); 52 | int msgid = 1; 53 | MQTTString topicString = MQTTString_initializer; 54 | int req_qos = 0; 55 | char* payload = "mypayload"; 56 | int payloadlen = strlen(payload); 57 | int len = 0; 58 | char *host = "m2m.eclipse.org"; 59 | int port = 1883; 60 | 61 | stop_init(); 62 | if (argc > 1) 63 | host = argv[1]; 64 | 65 | if (argc > 2) 66 | port = atoi(argv[2]); 67 | 68 | mysock = transport_open(host, port); 69 | if(mysock < 0) 70 | return mysock; 71 | 72 | printf("Sending to hostname %s port %d\n", host, port); 73 | 74 | data.clientID.cstring = "me"; 75 | data.keepAliveInterval = 20; 76 | data.cleansession = 1; 77 | data.username.cstring = "testuser"; 78 | data.password.cstring = "testpassword"; 79 | 80 | len = MQTTSerialize_connect(buf, buflen, &data); 81 | rc = transport_sendPacketBuffer(mysock, buf, len); 82 | 83 | /* wait for connack */ 84 | if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK) 85 | { 86 | unsigned char sessionPresent, connack_rc; 87 | 88 | if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0) 89 | { 90 | printf("Unable to connect, return code %d\n", connack_rc); 91 | goto exit; 92 | } 93 | } 94 | else 95 | goto exit; 96 | 97 | /* subscribe */ 98 | topicString.cstring = "substopic"; 99 | len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos); 100 | 101 | rc = transport_sendPacketBuffer(mysock, buf, len); 102 | if (MQTTPacket_read(buf, buflen, transport_getdata) == SUBACK) /* wait for suback */ 103 | { 104 | unsigned short submsgid; 105 | int subcount; 106 | int granted_qos; 107 | 108 | rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen); 109 | if (granted_qos != 0) 110 | { 111 | printf("granted qos != 0, %d\n", granted_qos); 112 | goto exit; 113 | } 114 | } 115 | else 116 | goto exit; 117 | 118 | /* loop getting msgs on subscribed topic */ 119 | topicString.cstring = "pubtopic"; 120 | while (!toStop) 121 | { 122 | /* transport_getdata() has a built-in 1 second timeout, 123 | your mileage will vary */ 124 | if (MQTTPacket_read(buf, buflen, transport_getdata) == PUBLISH) 125 | { 126 | unsigned char dup; 127 | int qos; 128 | unsigned char retained; 129 | unsigned short msgid; 130 | int payloadlen_in; 131 | unsigned char* payload_in; 132 | int rc; 133 | MQTTString receivedTopic; 134 | 135 | rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic, 136 | &payload_in, &payloadlen_in, buf, buflen); 137 | printf("message arrived %.*s\n", payloadlen_in, payload_in); 138 | } 139 | 140 | printf("publishing reading\n"); 141 | len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen); 142 | rc = transport_sendPacketBuffer(mysock, buf, len); 143 | } 144 | 145 | printf("disconnecting\n"); 146 | len = MQTTSerialize_disconnect(buf, buflen); 147 | rc = transport_sendPacketBuffer(mysock, buf, len); 148 | 149 | exit: 150 | transport_close(mysock); 151 | 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /MQTTPacket/samples/pub0sub1_nb.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - clarifications and/or documentation extension 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "MQTTPacket.h" 23 | #include "transport.h" 24 | 25 | /* This is in order to get an asynchronous signal to stop the sample, 26 | as the code loops waiting for msgs on the subscribed topic. 27 | Your actual code will depend on your hw and approach*/ 28 | #include 29 | 30 | int toStop = 0; 31 | 32 | void cfinish(int sig) 33 | { 34 | signal(SIGINT, NULL); 35 | toStop = 1; 36 | } 37 | 38 | void stop_init(void) 39 | { 40 | signal(SIGINT, cfinish); 41 | signal(SIGTERM, cfinish); 42 | } 43 | /* */ 44 | 45 | int main(int argc, char *argv[]) 46 | { 47 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 48 | int rc = 0; 49 | int mysock = 0; 50 | unsigned char buf[200]; 51 | int buflen = sizeof(buf); 52 | int msgid = 1; 53 | MQTTString topicString = MQTTString_initializer; 54 | int req_qos = 0; 55 | char* payload = "mypayload"; 56 | int payloadlen = strlen(payload); 57 | int len = 0; 58 | char *host = "m2m.eclipse.org"; 59 | int port = 1883; 60 | MQTTTransport mytransport; 61 | 62 | stop_init(); 63 | if (argc > 1) 64 | host = argv[1]; 65 | 66 | if (argc > 2) 67 | port = atoi(argv[2]); 68 | 69 | mysock = transport_open(host, port); 70 | if(mysock < 0) 71 | return mysock; 72 | 73 | printf("Sending to hostname %s port %d\n", host, port); 74 | 75 | mytransport.sck = &mysock; 76 | mytransport.getfn = transport_getdatanb; 77 | mytransport.state = 0; 78 | data.clientID.cstring = "me"; 79 | data.keepAliveInterval = 20; 80 | data.cleansession = 1; 81 | data.username.cstring = "testuser"; 82 | data.password.cstring = "testpassword"; 83 | 84 | len = MQTTSerialize_connect(buf, buflen, &data); 85 | rc = transport_sendPacketBuffer(mysock, buf, len); 86 | 87 | /* wait for connack */ 88 | if (MQTTPacket_read(buf, buflen, transport_getdata) == CONNACK) 89 | { 90 | unsigned char sessionPresent, connack_rc; 91 | 92 | if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) != 1 || connack_rc != 0) 93 | { 94 | printf("Unable to connect, return code %d\n", connack_rc); 95 | goto exit; 96 | } 97 | } 98 | else 99 | goto exit; 100 | 101 | /* subscribe */ 102 | topicString.cstring = "substopic"; 103 | len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos); 104 | 105 | rc = transport_sendPacketBuffer(mysock, buf, len); 106 | do { 107 | int frc; 108 | if ((frc=MQTTPacket_readnb(buf, buflen, &mytransport)) == SUBACK) /* wait for suback */ 109 | { 110 | unsigned short submsgid; 111 | int subcount; 112 | int granted_qos; 113 | 114 | rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen); 115 | if (granted_qos != 0) 116 | { 117 | printf("granted qos != 0, %d\n", granted_qos); 118 | goto exit; 119 | } 120 | break; 121 | } 122 | else if (frc == -1) 123 | goto exit; 124 | } while (1); /* handle timeouts here */ 125 | /* loop getting msgs on subscribed topic */ 126 | topicString.cstring = "pubtopic"; 127 | while (!toStop) 128 | { 129 | /* handle timeouts */ 130 | if (MQTTPacket_readnb(buf, buflen, &mytransport) == PUBLISH) 131 | { 132 | unsigned char dup; 133 | int qos; 134 | unsigned char retained; 135 | unsigned short msgid; 136 | int payloadlen_in; 137 | unsigned char* payload_in; 138 | int rc; 139 | MQTTString receivedTopic; 140 | 141 | rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic, 142 | &payload_in, &payloadlen_in, buf, buflen); 143 | printf("message arrived %.*s\n", payloadlen_in, payload_in); 144 | printf("publishing reading\n"); 145 | len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, (unsigned char*)payload, payloadlen); 146 | rc = transport_sendPacketBuffer(mysock, buf, len); 147 | } 148 | } 149 | 150 | printf("disconnecting\n"); 151 | len = MQTTSerialize_disconnect(buf, buflen); 152 | rc = transport_sendPacketBuffer(mysock, buf, len); 153 | 154 | exit: 155 | transport_close(mysock); 156 | 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /MQTTPacket/samples/qos0pub.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - clarifications and/or documentation extension 16 | *******************************************************************************/ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "MQTTPacket.h" 23 | #include "transport.h" 24 | 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 29 | int rc = 0; 30 | char buf[200]; 31 | int buflen = sizeof(buf); 32 | int mysock = 0; 33 | MQTTString topicString = MQTTString_initializer; 34 | char* payload = "mypayload"; 35 | int payloadlen = strlen(payload); 36 | int len = 0; 37 | char *host = "m2m.eclipse.org"; 38 | int port = 1883; 39 | 40 | if (argc > 1) 41 | host = argv[1]; 42 | 43 | if (argc > 2) 44 | port = atoi(argv[2]); 45 | 46 | mysock = transport_open(host,port); 47 | if(mysock < 0) 48 | return mysock; 49 | 50 | printf("Sending to hostname %s port %d\n", host, port); 51 | 52 | data.clientID.cstring = "me"; 53 | data.keepAliveInterval = 20; 54 | data.cleansession = 1; 55 | data.username.cstring = "testuser"; 56 | data.password.cstring = "testpassword"; 57 | data.MQTTVersion = 4; 58 | 59 | len = MQTTSerialize_connect((unsigned char *)buf, buflen, &data); 60 | 61 | topicString.cstring = "mytopic"; 62 | len += MQTTSerialize_publish((unsigned char *)(buf + len), buflen - len, 0, 0, 0, 0, topicString, (unsigned char *)payload, payloadlen); 63 | 64 | len += MQTTSerialize_disconnect((unsigned char *)(buf + len), buflen - len); 65 | 66 | rc = transport_sendPacketBuffer(mysock, (unsigned char*)buf, len); 67 | if (rc == len) 68 | printf("Successfully published\n"); 69 | else 70 | printf("Publish failed\n"); 71 | 72 | exit: 73 | transport_close(mysock); 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /MQTTPacket/samples/transport.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension 16 | *******************************************************************************/ 17 | 18 | #include 19 | 20 | #if !defined(SOCKET_ERROR) 21 | /** error in socket operation */ 22 | #define SOCKET_ERROR -1 23 | #endif 24 | 25 | #if defined(WIN32) 26 | /* default on Windows is 64 - increase to make Linux and Windows the same */ 27 | #define FD_SETSIZE 1024 28 | #include 29 | #include 30 | #define MAXHOSTNAMELEN 256 31 | #define EAGAIN WSAEWOULDBLOCK 32 | #define EINTR WSAEINTR 33 | #define EINVAL WSAEINVAL 34 | #define EINPROGRESS WSAEINPROGRESS 35 | #define EWOULDBLOCK WSAEWOULDBLOCK 36 | #define ENOTCONN WSAENOTCONN 37 | #define ECONNRESET WSAECONNRESET 38 | #define ioctl ioctlsocket 39 | #define socklen_t int 40 | #else 41 | #define INVALID_SOCKET SOCKET_ERROR 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #endif 56 | 57 | #if defined(WIN32) 58 | #include 59 | #else 60 | #include 61 | #include 62 | #endif 63 | 64 | /** 65 | This simple low-level implementation assumes a single connection for a single thread. Thus, a static 66 | variable is used for that connection. 67 | On other scenarios, the user must solve this by taking into account that the current implementation of 68 | MQTTPacket_read() has a function pointer for a function call to get the data to a buffer, but no provisions 69 | to know the caller or other indicator (the socket id): int (*getfn)(unsigned char*, int) 70 | */ 71 | static int mysock = INVALID_SOCKET; 72 | 73 | 74 | int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen) 75 | { 76 | int rc = 0; 77 | rc = write(sock, buf, buflen); 78 | return rc; 79 | } 80 | 81 | 82 | int transport_getdata(unsigned char* buf, int count) 83 | { 84 | int rc = recv(mysock, buf, count, 0); 85 | //printf("received %d bytes count %d\n", rc, (int)count); 86 | return rc; 87 | } 88 | 89 | int transport_getdatanb(void *sck, unsigned char* buf, int count) 90 | { 91 | int sock = *((int *)sck); /* sck: pointer to whatever the system may use to identify the transport */ 92 | /* this call will return after the timeout set on initialization if no bytes; 93 | in your system you will use whatever you use to get whichever outstanding 94 | bytes your socket equivalent has ready to be extracted right now, if any, 95 | or return immediately */ 96 | int rc = recv(sock, buf, count, 0); 97 | if (rc == -1) { 98 | /* check error conditions from your system here, and return -1 */ 99 | return 0; 100 | } 101 | return rc; 102 | } 103 | 104 | /** 105 | return >=0 for a socket descriptor, <0 for an error code 106 | @todo Basically moved from the sample without changes, should accomodate same usage for 'sock' for clarity, 107 | removing indirections 108 | */ 109 | int transport_open(char* addr, int port) 110 | { 111 | int* sock = &mysock; 112 | int type = SOCK_STREAM; 113 | struct sockaddr_in address; 114 | #if defined(AF_INET6) 115 | struct sockaddr_in6 address6; 116 | #endif 117 | int rc = -1; 118 | #if defined(WIN32) 119 | short family; 120 | #else 121 | sa_family_t family = AF_INET; 122 | #endif 123 | struct addrinfo *result = NULL; 124 | struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL}; 125 | static struct timeval tv; 126 | 127 | *sock = -1; 128 | if (addr[0] == '[') 129 | ++addr; 130 | 131 | if ((rc = getaddrinfo(addr, NULL, &hints, &result)) == 0) 132 | { 133 | struct addrinfo* res = result; 134 | 135 | /* prefer ip4 addresses */ 136 | while (res) 137 | { 138 | if (res->ai_family == AF_INET) 139 | { 140 | result = res; 141 | break; 142 | } 143 | res = res->ai_next; 144 | } 145 | 146 | #if defined(AF_INET6) 147 | if (result->ai_family == AF_INET6) 148 | { 149 | address6.sin6_port = htons(port); 150 | address6.sin6_family = family = AF_INET6; 151 | address6.sin6_addr = ((struct sockaddr_in6*)(result->ai_addr))->sin6_addr; 152 | } 153 | else 154 | #endif 155 | if (result->ai_family == AF_INET) 156 | { 157 | address.sin_port = htons(port); 158 | address.sin_family = family = AF_INET; 159 | address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr; 160 | } 161 | else 162 | rc = -1; 163 | 164 | freeaddrinfo(result); 165 | } 166 | 167 | if (rc == 0) 168 | { 169 | *sock = socket(family, type, 0); 170 | if (*sock != -1) 171 | { 172 | #if defined(NOSIGPIPE) 173 | int opt = 1; 174 | 175 | if (setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0) 176 | Log(TRACE_MIN, -1, "Could not set SO_NOSIGPIPE for socket %d", *sock); 177 | #endif 178 | 179 | if (family == AF_INET) 180 | rc = connect(*sock, (struct sockaddr*)&address, sizeof(address)); 181 | #if defined(AF_INET6) 182 | else 183 | rc = connect(*sock, (struct sockaddr*)&address6, sizeof(address6)); 184 | #endif 185 | } 186 | } 187 | if (mysock == INVALID_SOCKET) 188 | return rc; 189 | 190 | tv.tv_sec = 1; /* 1 second Timeout */ 191 | tv.tv_usec = 0; 192 | setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); 193 | return mysock; 194 | } 195 | 196 | int transport_close(int sock) 197 | { 198 | int rc; 199 | 200 | rc = shutdown(sock, SHUT_WR); 201 | rc = recv(sock, NULL, (size_t)0, 0); 202 | rc = close(sock); 203 | 204 | return rc; 205 | } 206 | -------------------------------------------------------------------------------- /MQTTPacket/samples/transport.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Sergio R. Caprile - "commonalization" from prior samples and/or documentation extension 16 | *******************************************************************************/ 17 | 18 | int transport_sendPacketBuffer(int sock, unsigned char* buf, int buflen); 19 | int transport_getdata(unsigned char* buf, int count); 20 | int transport_getdatanb(void *sck, unsigned char* buf, int count); 21 | int transport_open(char* host, int port); 22 | int transport_close(int sock); 23 | -------------------------------------------------------------------------------- /MQTTPacket/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Ian Craggs - initial version 15 | #*******************************************************************************/ 16 | 17 | # MQTTPacket Library 18 | file(GLOB SOURCES "*.c") 19 | add_library(paho-embed-mqtt3c SHARED ${SOURCES}) 20 | install(TARGETS paho-embed-mqtt3c DESTINATION /usr/lib) 21 | target_compile_definitions(paho-embed-mqtt3c PRIVATE MQTT_SERVER MQTT_CLIENT) 22 | 23 | add_library(MQTTPacketClient SHARED MQTTFormat MQTTPacket 24 | MQTTSerializePublish MQTTDeserializePublish 25 | MQTTConnectClient MQTTSubscribeClient MQTTUnsubscribeClient) 26 | target_compile_definitions(MQTTPacketClient PRIVATE MQTT_CLIENT) 27 | 28 | add_library(MQTTPacketServer SHARED MQTTFormat MQTTPacket 29 | MQTTSerializePublish MQTTDeserializePublish 30 | MQTTConnectServer MQTTSubscribeServer MQTTUnsubscribeServer) 31 | target_compile_definitions(MQTTPacketServer PRIVATE MQTT_SERVER) 32 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTConnect.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2017 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - add connack return code definitions 16 | * Xiang Rong - 442039 Add makefile to Embedded C client 17 | * Ian Craggs - fix for issue #64, bit order in connack response 18 | *******************************************************************************/ 19 | 20 | #ifndef MQTTCONNECT_H_ 21 | #define MQTTCONNECT_H_ 22 | 23 | enum connack_return_codes 24 | { 25 | MQTT_CONNECTION_ACCEPTED = 0, 26 | MQTT_UNNACCEPTABLE_PROTOCOL = 1, 27 | MQTT_CLIENTID_REJECTED = 2, 28 | MQTT_SERVER_UNAVAILABLE = 3, 29 | MQTT_BAD_USERNAME_OR_PASSWORD = 4, 30 | MQTT_NOT_AUTHORIZED = 5, 31 | }; 32 | 33 | #if !defined(DLLImport) 34 | #define DLLImport 35 | #endif 36 | #if !defined(DLLExport) 37 | #define DLLExport 38 | #endif 39 | 40 | 41 | typedef union 42 | { 43 | unsigned char all; /**< all connect flags */ 44 | #if defined(REVERSED) 45 | struct 46 | { 47 | unsigned int username : 1; /**< 3.1 user name */ 48 | unsigned int password : 1; /**< 3.1 password */ 49 | unsigned int willRetain : 1; /**< will retain setting */ 50 | unsigned int willQoS : 2; /**< will QoS value */ 51 | unsigned int will : 1; /**< will flag */ 52 | unsigned int cleansession : 1; /**< clean session flag */ 53 | unsigned int : 1; /**< unused */ 54 | } bits; 55 | #else 56 | struct 57 | { 58 | unsigned int : 1; /**< unused */ 59 | unsigned int cleansession : 1; /**< cleansession flag */ 60 | unsigned int will : 1; /**< will flag */ 61 | unsigned int willQoS : 2; /**< will QoS value */ 62 | unsigned int willRetain : 1; /**< will retain setting */ 63 | unsigned int password : 1; /**< 3.1 password */ 64 | unsigned int username : 1; /**< 3.1 user name */ 65 | } bits; 66 | #endif 67 | } MQTTConnectFlags; /**< connect flags byte */ 68 | 69 | 70 | 71 | /** 72 | * Defines the MQTT "Last Will and Testament" (LWT) settings for 73 | * the connect packet. 74 | */ 75 | typedef struct 76 | { 77 | /** The eyecatcher for this structure. must be MQTW. */ 78 | char struct_id[4]; 79 | /** The version number of this structure. Must be 0 */ 80 | int struct_version; 81 | /** The LWT topic to which the LWT message will be published. */ 82 | MQTTString topicName; 83 | /** The LWT payload. */ 84 | MQTTString message; 85 | /** 86 | * The retained flag for the LWT message (see MQTTAsync_message.retained). 87 | */ 88 | unsigned char retained; 89 | /** 90 | * The quality of service setting for the LWT message (see 91 | * MQTTAsync_message.qos and @ref qos). 92 | */ 93 | char qos; 94 | } MQTTPacket_willOptions; 95 | 96 | 97 | #define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 } 98 | 99 | 100 | typedef struct 101 | { 102 | /** The eyecatcher for this structure. must be MQTC. */ 103 | char struct_id[4]; 104 | /** The version number of this structure. Must be 0 */ 105 | int struct_version; 106 | /** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1 107 | */ 108 | unsigned char MQTTVersion; 109 | MQTTString clientID; 110 | unsigned short keepAliveInterval; 111 | unsigned char cleansession; 112 | unsigned char willFlag; 113 | MQTTPacket_willOptions will; 114 | MQTTString username; 115 | MQTTString password; 116 | } MQTTPacket_connectData; 117 | 118 | typedef union 119 | { 120 | unsigned char all; /**< all connack flags */ 121 | #if defined(REVERSED) 122 | struct 123 | { 124 | unsigned int reserved : 7; /**< unused */ 125 | unsigned int sessionpresent : 1; /**< session present flag */ 126 | } bits; 127 | #else 128 | struct 129 | { 130 | unsigned int sessionpresent : 1; /**< session present flag */ 131 | unsigned int reserved: 7; /**< unused */ 132 | } bits; 133 | #endif 134 | } MQTTConnackFlags; /**< connack flags byte */ 135 | 136 | #define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \ 137 | MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} } 138 | 139 | DLLExport int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options); 140 | DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len); 141 | 142 | DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent); 143 | DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen); 144 | 145 | DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen); 146 | DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen); 147 | 148 | #endif /* MQTTCONNECT_H_ */ 149 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTConnectClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include "StackTrace.h" 19 | 20 | #include 21 | 22 | /** 23 | * Determines the length of the MQTT connect packet that would be produced using the supplied connect options. 24 | * @param options the options to be used to build the connect packet 25 | * @return the length of buffer needed to contain the serialized version of the packet 26 | */ 27 | int MQTTSerialize_connectLength(MQTTPacket_connectData* options) 28 | { 29 | int len = 0; 30 | 31 | FUNC_ENTRY; 32 | 33 | if (options->MQTTVersion == 3) 34 | len = 12; /* variable depending on MQTT or MQIsdp */ 35 | else if (options->MQTTVersion == 4) 36 | len = 10; 37 | 38 | len += MQTTstrlen(options->clientID)+2; 39 | if (options->willFlag) 40 | len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2; 41 | if (options->username.cstring || options->username.lenstring.data) 42 | len += MQTTstrlen(options->username)+2; 43 | if (options->password.cstring || options->password.lenstring.data) 44 | len += MQTTstrlen(options->password)+2; 45 | 46 | FUNC_EXIT_RC(len); 47 | return len; 48 | } 49 | 50 | 51 | /** 52 | * Serializes the connect options into the buffer. 53 | * @param buf the buffer into which the packet will be serialized 54 | * @param len the length in bytes of the supplied buffer 55 | * @param options the options to be used to build the connect packet 56 | * @return serialized length, or error if 0 57 | */ 58 | int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options) 59 | { 60 | unsigned char *ptr = buf; 61 | MQTTHeader header = {0}; 62 | MQTTConnectFlags flags = {0}; 63 | int len = 0; 64 | int rc = -1; 65 | 66 | FUNC_ENTRY; 67 | if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen) 68 | { 69 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 70 | goto exit; 71 | } 72 | 73 | header.byte = 0; 74 | header.bits.type = CONNECT; 75 | writeChar(&ptr, header.byte); /* write header */ 76 | 77 | ptr += MQTTPacket_encode(ptr, len); /* write remaining length */ 78 | 79 | if (options->MQTTVersion == 4) 80 | { 81 | writeCString(&ptr, "MQTT"); 82 | writeChar(&ptr, (char) 4); 83 | } 84 | else 85 | { 86 | writeCString(&ptr, "MQIsdp"); 87 | writeChar(&ptr, (char) 3); 88 | } 89 | 90 | flags.all = 0; 91 | flags.bits.cleansession = options->cleansession; 92 | flags.bits.will = (options->willFlag) ? 1 : 0; 93 | if (flags.bits.will) 94 | { 95 | flags.bits.willQoS = options->will.qos; 96 | flags.bits.willRetain = options->will.retained; 97 | } 98 | 99 | if (options->username.cstring || options->username.lenstring.data) 100 | flags.bits.username = 1; 101 | if (options->password.cstring || options->password.lenstring.data) 102 | flags.bits.password = 1; 103 | 104 | writeChar(&ptr, flags.all); 105 | writeInt(&ptr, options->keepAliveInterval); 106 | writeMQTTString(&ptr, options->clientID); 107 | if (options->willFlag) 108 | { 109 | writeMQTTString(&ptr, options->will.topicName); 110 | writeMQTTString(&ptr, options->will.message); 111 | } 112 | if (flags.bits.username) 113 | writeMQTTString(&ptr, options->username); 114 | if (flags.bits.password) 115 | writeMQTTString(&ptr, options->password); 116 | 117 | rc = ptr - buf; 118 | 119 | exit: FUNC_EXIT_RC(rc); 120 | return rc; 121 | } 122 | 123 | 124 | /** 125 | * Deserializes the supplied (wire) buffer into connack data - return code 126 | * @param sessionPresent the session present flag returned (only for MQTT 3.1.1) 127 | * @param connack_rc returned integer value of the connack return code 128 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 129 | * @param len the length in bytes of the data in the supplied buffer 130 | * @return error code. 1 is success, 0 is failure 131 | */ 132 | int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen) 133 | { 134 | MQTTHeader header = {0}; 135 | unsigned char* curdata = buf; 136 | unsigned char* enddata = NULL; 137 | int rc = 0; 138 | int mylen; 139 | MQTTConnackFlags flags = {0}; 140 | 141 | FUNC_ENTRY; 142 | header.byte = readChar(&curdata); 143 | if (header.bits.type != CONNACK) 144 | goto exit; 145 | 146 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 147 | enddata = curdata + mylen; 148 | if (enddata - curdata < 2) 149 | goto exit; 150 | 151 | flags.all = readChar(&curdata); 152 | *sessionPresent = flags.bits.sessionpresent; 153 | *connack_rc = readChar(&curdata); 154 | 155 | rc = 1; 156 | exit: 157 | FUNC_EXIT_RC(rc); 158 | return rc; 159 | } 160 | 161 | 162 | /** 163 | * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket 164 | * @param buf the buffer into which the packet will be serialized 165 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 166 | * @param packettype the message type 167 | * @return serialized length, or error if 0 168 | */ 169 | int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype) 170 | { 171 | MQTTHeader header = {0}; 172 | int rc = -1; 173 | unsigned char *ptr = buf; 174 | 175 | FUNC_ENTRY; 176 | if (buflen < 2) 177 | { 178 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 179 | goto exit; 180 | } 181 | header.byte = 0; 182 | header.bits.type = packettype; 183 | writeChar(&ptr, header.byte); /* write header */ 184 | 185 | ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */ 186 | rc = ptr - buf; 187 | exit: 188 | FUNC_EXIT_RC(rc); 189 | return rc; 190 | } 191 | 192 | 193 | /** 194 | * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 195 | * @param buf the buffer into which the packet will be serialized 196 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 197 | * @return serialized length, or error if 0 198 | */ 199 | int MQTTSerialize_disconnect(unsigned char* buf, int buflen) 200 | { 201 | return MQTTSerialize_zero(buf, buflen, DISCONNECT); 202 | } 203 | 204 | 205 | /** 206 | * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket 207 | * @param buf the buffer into which the packet will be serialized 208 | * @param buflen the length in bytes of the supplied buffer, to avoid overruns 209 | * @return serialized length, or error if 0 210 | */ 211 | int MQTTSerialize_pingreq(unsigned char* buf, int buflen) 212 | { 213 | return MQTTSerialize_zero(buf, buflen, PINGREQ); 214 | } 215 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTConnectServer.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "StackTrace.h" 18 | #include "MQTTPacket.h" 19 | #include 20 | 21 | #define min(a, b) ((a < b) ? a : b) 22 | 23 | 24 | /** 25 | * Validates MQTT protocol name and version combinations 26 | * @param protocol the MQTT protocol name as an MQTTString 27 | * @param version the MQTT protocol version number, as in the connect packet 28 | * @return correct MQTT combination? 1 is true, 0 is false 29 | */ 30 | int MQTTPacket_checkVersion(MQTTString* protocol, int version) 31 | { 32 | int rc = 0; 33 | 34 | if (version == 3 && memcmp(protocol->lenstring.data, "MQIsdp", 35 | min(6, protocol->lenstring.len)) == 0) 36 | rc = 1; 37 | else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT", 38 | min(4, protocol->lenstring.len)) == 0) 39 | rc = 1; 40 | return rc; 41 | } 42 | 43 | 44 | /** 45 | * Deserializes the supplied (wire) buffer into connect data structure 46 | * @param data the connect data structure to be filled out 47 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 48 | * @param len the length in bytes of the data in the supplied buffer 49 | * @return error code. 1 is success, 0 is failure 50 | */ 51 | int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len) 52 | { 53 | MQTTHeader header = {0}; 54 | MQTTConnectFlags flags = {0}; 55 | unsigned char* curdata = buf; 56 | unsigned char* enddata = &buf[len]; 57 | int rc = 0; 58 | MQTTString Protocol; 59 | int version; 60 | int mylen = 0; 61 | 62 | FUNC_ENTRY; 63 | header.byte = readChar(&curdata); 64 | if (header.bits.type != CONNECT) 65 | goto exit; 66 | 67 | curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */ 68 | 69 | if (!readMQTTLenString(&Protocol, &curdata, enddata) || 70 | enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */ 71 | goto exit; 72 | 73 | version = (int)readChar(&curdata); /* Protocol version */ 74 | /* If we don't recognize the protocol version, we don't parse the connect packet on the 75 | * basis that we don't know what the format will be. 76 | */ 77 | if (MQTTPacket_checkVersion(&Protocol, version)) 78 | { 79 | flags.all = readChar(&curdata); 80 | data->cleansession = flags.bits.cleansession; 81 | data->keepAliveInterval = readInt(&curdata); 82 | if (!readMQTTLenString(&data->clientID, &curdata, enddata)) 83 | goto exit; 84 | data->willFlag = flags.bits.will; 85 | if (flags.bits.will) 86 | { 87 | data->will.qos = flags.bits.willQoS; 88 | data->will.retained = flags.bits.willRetain; 89 | if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) || 90 | !readMQTTLenString(&data->will.message, &curdata, enddata)) 91 | goto exit; 92 | } 93 | if (flags.bits.username) 94 | { 95 | if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata)) 96 | goto exit; /* username flag set, but no username supplied - invalid */ 97 | if (flags.bits.password && 98 | (enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata))) 99 | goto exit; /* password flag set, but no password supplied - invalid */ 100 | } 101 | else if (flags.bits.password) 102 | goto exit; /* password flag set without username - invalid */ 103 | rc = 1; 104 | } 105 | exit: 106 | FUNC_EXIT_RC(rc); 107 | return rc; 108 | } 109 | 110 | 111 | /** 112 | * Serializes the connack packet into the supplied buffer. 113 | * @param buf the buffer into which the packet will be serialized 114 | * @param buflen the length in bytes of the supplied buffer 115 | * @param connack_rc the integer connack return code to be used 116 | * @param sessionPresent the MQTT 3.1.1 sessionPresent flag 117 | * @return serialized length, or error if 0 118 | */ 119 | int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent) 120 | { 121 | MQTTHeader header = {0}; 122 | int rc = 0; 123 | unsigned char *ptr = buf; 124 | MQTTConnackFlags flags = {0}; 125 | 126 | FUNC_ENTRY; 127 | if (buflen < 2) 128 | { 129 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 130 | goto exit; 131 | } 132 | header.byte = 0; 133 | header.bits.type = CONNACK; 134 | writeChar(&ptr, header.byte); /* write header */ 135 | 136 | ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */ 137 | 138 | flags.all = 0; 139 | flags.bits.sessionpresent = sessionPresent; 140 | writeChar(&ptr, flags.all); 141 | writeChar(&ptr, connack_rc); 142 | 143 | rc = ptr - buf; 144 | exit: 145 | FUNC_EXIT_RC(rc); 146 | return rc; 147 | } 148 | 149 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTDeserializePublish.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "StackTrace.h" 18 | #include "MQTTPacket.h" 19 | #include 20 | 21 | #define min(a, b) ((a < b) ? 1 : 0) 22 | 23 | /** 24 | * Deserializes the supplied (wire) buffer into publish data 25 | * @param dup returned integer - the MQTT dup flag 26 | * @param qos returned integer - the MQTT QoS value 27 | * @param retained returned integer - the MQTT retained flag 28 | * @param packetid returned integer - the MQTT packet identifier 29 | * @param topicName returned MQTTString - the MQTT topic in the publish 30 | * @param payload returned byte buffer - the MQTT publish payload 31 | * @param payloadlen returned integer - the length of the MQTT payload 32 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 33 | * @param buflen the length in bytes of the data in the supplied buffer 34 | * @return error code. 1 is success 35 | */ 36 | int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, 37 | unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen) 38 | { 39 | MQTTHeader header = {0}; 40 | unsigned char* curdata = buf; 41 | unsigned char* enddata = NULL; 42 | int rc = 0; 43 | int mylen = 0; 44 | 45 | FUNC_ENTRY; 46 | header.byte = readChar(&curdata); 47 | if (header.bits.type != PUBLISH) 48 | goto exit; 49 | *dup = header.bits.dup; 50 | *qos = header.bits.qos; 51 | *retained = header.bits.retain; 52 | 53 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 54 | enddata = curdata + mylen; 55 | 56 | if (!readMQTTLenString(topicName, &curdata, enddata) || 57 | enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */ 58 | goto exit; 59 | 60 | if (*qos > 0) 61 | *packetid = readInt(&curdata); 62 | 63 | *payloadlen = enddata - curdata; 64 | *payload = curdata; 65 | rc = 1; 66 | exit: 67 | FUNC_EXIT_RC(rc); 68 | return rc; 69 | } 70 | 71 | 72 | 73 | /** 74 | * Deserializes the supplied (wire) buffer into an ack 75 | * @param packettype returned integer - the MQTT packet type 76 | * @param dup returned integer - the MQTT dup flag 77 | * @param packetid returned integer - the MQTT packet identifier 78 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 79 | * @param buflen the length in bytes of the data in the supplied buffer 80 | * @return error code. 1 is success, 0 is failure 81 | */ 82 | int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen) 83 | { 84 | MQTTHeader header = {0}; 85 | unsigned char* curdata = buf; 86 | unsigned char* enddata = NULL; 87 | int rc = 0; 88 | int mylen; 89 | 90 | FUNC_ENTRY; 91 | header.byte = readChar(&curdata); 92 | *dup = header.bits.dup; 93 | *packettype = header.bits.type; 94 | 95 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 96 | enddata = curdata + mylen; 97 | 98 | if (enddata - curdata < 2) 99 | goto exit; 100 | *packetid = readInt(&curdata); 101 | 102 | rc = 1; 103 | exit: 104 | FUNC_EXIT_RC(rc); 105 | return rc; 106 | } 107 | 108 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTFormat.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #if !defined(MQTTFORMAT_H) 18 | #define MQTTFORMAT_H 19 | 20 | #include "StackTrace.h" 21 | #include "MQTTPacket.h" 22 | 23 | const char* MQTTPacket_getName(unsigned short packetid); 24 | int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data); 25 | int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent); 26 | int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained, 27 | unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen); 28 | int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid); 29 | int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count, 30 | MQTTString topicFilters[], int requestedQoSs[]); 31 | int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs); 32 | int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, 33 | int count, MQTTString topicFilters[]); 34 | char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen); 35 | char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTPacket.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTPACKET_H_ 19 | #define MQTTPACKET_H_ 20 | 21 | #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ 22 | extern "C" { 23 | #endif 24 | 25 | #if defined(WIN32_DLL) || defined(WIN64_DLL) 26 | #define DLLImport __declspec(dllimport) 27 | #define DLLExport __declspec(dllexport) 28 | #elif defined(LINUX_SO) 29 | #define DLLImport extern 30 | #define DLLExport __attribute__ ((visibility ("default"))) 31 | #else 32 | #define DLLImport 33 | #define DLLExport 34 | #endif 35 | 36 | enum errors 37 | { 38 | MQTTPACKET_BUFFER_TOO_SHORT = -2, 39 | MQTTPACKET_READ_ERROR = -1, 40 | MQTTPACKET_READ_COMPLETE 41 | }; 42 | 43 | enum msgTypes 44 | { 45 | CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, 46 | PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, 47 | PINGREQ, PINGRESP, DISCONNECT 48 | }; 49 | 50 | /** 51 | * Bitfields for the MQTT header byte. 52 | */ 53 | typedef union 54 | { 55 | unsigned char byte; /**< the whole byte */ 56 | #if defined(REVERSED) 57 | struct 58 | { 59 | unsigned int type : 4; /**< message type nibble */ 60 | unsigned int dup : 1; /**< DUP flag bit */ 61 | unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ 62 | unsigned int retain : 1; /**< retained flag bit */ 63 | } bits; 64 | #else 65 | struct 66 | { 67 | unsigned int retain : 1; /**< retained flag bit */ 68 | unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ 69 | unsigned int dup : 1; /**< DUP flag bit */ 70 | unsigned int type : 4; /**< message type nibble */ 71 | } bits; 72 | #endif 73 | } MQTTHeader; 74 | 75 | typedef struct 76 | { 77 | int len; 78 | char* data; 79 | } MQTTLenString; 80 | 81 | typedef struct 82 | { 83 | char* cstring; 84 | MQTTLenString lenstring; 85 | } MQTTString; 86 | 87 | #define MQTTString_initializer {NULL, {0, NULL}} 88 | 89 | int MQTTstrlen(MQTTString mqttstring); 90 | 91 | #include "MQTTConnect.h" 92 | #include "MQTTPublish.h" 93 | #include "MQTTSubscribe.h" 94 | #include "MQTTUnsubscribe.h" 95 | #include "MQTTFormat.h" 96 | 97 | DLLExport int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid); 98 | DLLExport int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen); 99 | 100 | int MQTTPacket_len(int rem_len); 101 | DLLExport int MQTTPacket_equals(MQTTString* a, char* b); 102 | 103 | DLLExport int MQTTPacket_encode(unsigned char* buf, int length); 104 | int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value); 105 | int MQTTPacket_decodeBuf(unsigned char* buf, int* value); 106 | 107 | int readInt(unsigned char** pptr); 108 | char readChar(unsigned char** pptr); 109 | void writeChar(unsigned char** pptr, char c); 110 | void writeInt(unsigned char** pptr, int anInt); 111 | int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata); 112 | void writeCString(unsigned char** pptr, const char* string); 113 | void writeMQTTString(unsigned char** pptr, MQTTString mqttstring); 114 | 115 | DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int)); 116 | 117 | typedef struct { 118 | int (*getfn)(void *, unsigned char*, int); /* must return -1 for error, 0 for call again, or the number of bytes read */ 119 | void *sck; /* pointer to whatever the system may use to identify the transport */ 120 | int multiplier; 121 | int rem_len; 122 | int len; 123 | char state; 124 | }MQTTTransport; 125 | 126 | int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp); 127 | 128 | #ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ 129 | } 130 | #endif 131 | 132 | 133 | #endif /* MQTTPACKET_H_ */ 134 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTPublish.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTPUBLISH_H_ 19 | #define MQTTPUBLISH_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid, 29 | MQTTString topicName, unsigned char* payload, int payloadlen); 30 | 31 | DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, 32 | unsigned char** payload, int* payloadlen, unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid); 35 | DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid); 36 | DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid); 37 | 38 | #endif /* MQTTPUBLISH_H_ */ 39 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTSerializePublish.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144 16 | *******************************************************************************/ 17 | 18 | #include "MQTTPacket.h" 19 | #include "StackTrace.h" 20 | 21 | #include 22 | 23 | 24 | /** 25 | * Determines the length of the MQTT publish packet that would be produced using the supplied parameters 26 | * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0) 27 | * @param topicName the topic name to be used in the publish 28 | * @param payloadlen the length of the payload to be sent 29 | * @return the length of buffer needed to contain the serialized version of the packet 30 | */ 31 | int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen) 32 | { 33 | int len = 0; 34 | 35 | len += 2 + MQTTstrlen(topicName) + payloadlen; 36 | if (qos > 0) 37 | len += 2; /* packetid */ 38 | return len; 39 | } 40 | 41 | 42 | /** 43 | * Serializes the supplied publish data into the supplied buffer, ready for sending 44 | * @param buf the buffer into which the packet will be serialized 45 | * @param buflen the length in bytes of the supplied buffer 46 | * @param dup integer - the MQTT dup flag 47 | * @param qos integer - the MQTT QoS value 48 | * @param retained integer - the MQTT retained flag 49 | * @param packetid integer - the MQTT packet identifier 50 | * @param topicName MQTTString - the MQTT topic in the publish 51 | * @param payload byte buffer - the MQTT publish payload 52 | * @param payloadlen integer - the length of the MQTT payload 53 | * @return the length of the serialized data. <= 0 indicates error 54 | */ 55 | int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid, 56 | MQTTString topicName, unsigned char* payload, int payloadlen) 57 | { 58 | unsigned char *ptr = buf; 59 | MQTTHeader header = {0}; 60 | int rem_len = 0; 61 | int rc = 0; 62 | 63 | FUNC_ENTRY; 64 | if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen) 65 | { 66 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 67 | goto exit; 68 | } 69 | 70 | header.bits.type = PUBLISH; 71 | header.bits.dup = dup; 72 | header.bits.qos = qos; 73 | header.bits.retain = retained; 74 | writeChar(&ptr, header.byte); /* write header */ 75 | 76 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 77 | 78 | writeMQTTString(&ptr, topicName); 79 | 80 | if (qos > 0) 81 | writeInt(&ptr, packetid); 82 | 83 | memcpy(ptr, payload, payloadlen); 84 | ptr += payloadlen; 85 | 86 | rc = ptr - buf; 87 | 88 | exit: 89 | FUNC_EXIT_RC(rc); 90 | return rc; 91 | } 92 | 93 | 94 | 95 | /** 96 | * Serializes the ack packet into the supplied buffer. 97 | * @param buf the buffer into which the packet will be serialized 98 | * @param buflen the length in bytes of the supplied buffer 99 | * @param type the MQTT packet type 100 | * @param dup the MQTT dup flag 101 | * @param packetid the MQTT packet identifier 102 | * @return serialized length, or error if 0 103 | */ 104 | int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid) 105 | { 106 | MQTTHeader header = {0}; 107 | int rc = 0; 108 | unsigned char *ptr = buf; 109 | 110 | FUNC_ENTRY; 111 | if (buflen < 4) 112 | { 113 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 114 | goto exit; 115 | } 116 | header.bits.type = packettype; 117 | header.bits.dup = dup; 118 | header.bits.qos = (packettype == PUBREL) ? 1 : 0; 119 | writeChar(&ptr, header.byte); /* write header */ 120 | 121 | ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */ 122 | writeInt(&ptr, packetid); 123 | rc = ptr - buf; 124 | exit: 125 | FUNC_EXIT_RC(rc); 126 | return rc; 127 | } 128 | 129 | 130 | /** 131 | * Serializes a puback packet into the supplied buffer. 132 | * @param buf the buffer into which the packet will be serialized 133 | * @param buflen the length in bytes of the supplied buffer 134 | * @param packetid integer - the MQTT packet identifier 135 | * @return serialized length, or error if 0 136 | */ 137 | int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid) 138 | { 139 | return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid); 140 | } 141 | 142 | 143 | /** 144 | * Serializes a pubrel packet into the supplied buffer. 145 | * @param buf the buffer into which the packet will be serialized 146 | * @param buflen the length in bytes of the supplied buffer 147 | * @param dup integer - the MQTT dup flag 148 | * @param packetid integer - the MQTT packet identifier 149 | * @return serialized length, or error if 0 150 | */ 151 | int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid) 152 | { 153 | return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid); 154 | } 155 | 156 | 157 | /** 158 | * Serializes a pubrel packet into the supplied buffer. 159 | * @param buf the buffer into which the packet will be serialized 160 | * @param buflen the length in bytes of the supplied buffer 161 | * @param packetid integer - the MQTT packet identifier 162 | * @return serialized length, or error if 0 163 | */ 164 | int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid) 165 | { 166 | return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid); 167 | } 168 | 169 | 170 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTSubscribe.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTSUBSCRIBE_H_ 19 | #define MQTTSUBSCRIBE_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 29 | int count, MQTTString topicFilters[], int requestedQoSs[]); 30 | 31 | DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, 32 | int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs); 35 | 36 | DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len); 37 | 38 | 39 | #endif /* MQTTSUBSCRIBE_H_ */ 40 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTSubscribeClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include "StackTrace.h" 19 | 20 | #include 21 | 22 | /** 23 | * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters 24 | * @param count the number of topic filter strings in topicFilters 25 | * @param topicFilters the array of topic filter strings to be used in the publish 26 | * @return the length of buffer needed to contain the serialized version of the packet 27 | */ 28 | int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[]) 29 | { 30 | int i; 31 | int len = 2; /* packetid */ 32 | 33 | for (i = 0; i < count; ++i) 34 | len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */ 35 | return len; 36 | } 37 | 38 | 39 | /** 40 | * Serializes the supplied subscribe data into the supplied buffer, ready for sending 41 | * @param buf the buffer into which the packet will be serialized 42 | * @param buflen the length in bytes of the supplied bufferr 43 | * @param dup integer - the MQTT dup flag 44 | * @param packetid integer - the MQTT packet identifier 45 | * @param count - number of members in the topicFilters and reqQos arrays 46 | * @param topicFilters - array of topic filter names 47 | * @param requestedQoSs - array of requested QoS 48 | * @return the length of the serialized data. <= 0 indicates error 49 | */ 50 | int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count, 51 | MQTTString topicFilters[], int requestedQoSs[]) 52 | { 53 | unsigned char *ptr = buf; 54 | MQTTHeader header = {0}; 55 | int rem_len = 0; 56 | int rc = 0; 57 | int i = 0; 58 | 59 | FUNC_ENTRY; 60 | if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen) 61 | { 62 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 63 | goto exit; 64 | } 65 | 66 | header.byte = 0; 67 | header.bits.type = SUBSCRIBE; 68 | header.bits.dup = dup; 69 | header.bits.qos = 1; 70 | writeChar(&ptr, header.byte); /* write header */ 71 | 72 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 73 | 74 | writeInt(&ptr, packetid); 75 | 76 | for (i = 0; i < count; ++i) 77 | { 78 | writeMQTTString(&ptr, topicFilters[i]); 79 | writeChar(&ptr, requestedQoSs[i]); 80 | } 81 | 82 | rc = ptr - buf; 83 | exit: 84 | FUNC_EXIT_RC(rc); 85 | return rc; 86 | } 87 | 88 | 89 | 90 | /** 91 | * Deserializes the supplied (wire) buffer into suback data 92 | * @param packetid returned integer - the MQTT packet identifier 93 | * @param maxcount - the maximum number of members allowed in the grantedQoSs array 94 | * @param count returned integer - number of members in the grantedQoSs array 95 | * @param grantedQoSs returned array of integers - the granted qualities of service 96 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 97 | * @param buflen the length in bytes of the data in the supplied buffer 98 | * @return error code. 1 is success, 0 is failure 99 | */ 100 | int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen) 101 | { 102 | MQTTHeader header = {0}; 103 | unsigned char* curdata = buf; 104 | unsigned char* enddata = NULL; 105 | int rc = 0; 106 | int mylen; 107 | 108 | FUNC_ENTRY; 109 | header.byte = readChar(&curdata); 110 | if (header.bits.type != SUBACK) 111 | goto exit; 112 | 113 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 114 | enddata = curdata + mylen; 115 | if (enddata - curdata < 2) 116 | goto exit; 117 | 118 | *packetid = readInt(&curdata); 119 | 120 | *count = 0; 121 | while (curdata < enddata) 122 | { 123 | if (*count > maxcount) 124 | { 125 | rc = -1; 126 | goto exit; 127 | } 128 | grantedQoSs[(*count)++] = readChar(&curdata); 129 | } 130 | 131 | rc = 1; 132 | exit: 133 | FUNC_EXIT_RC(rc); 134 | return rc; 135 | } 136 | 137 | 138 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTSubscribeServer.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014, 2023 IBM Corp., Ian Craggs 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include "StackTrace.h" 19 | 20 | #include 21 | 22 | 23 | /** 24 | * Deserializes the supplied (wire) buffer into subscribe data 25 | * @param dup integer returned - the MQTT dup flag 26 | * @param packetid integer returned - the MQTT packet identifier 27 | * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays 28 | * @param count - number of members in the topicFilters and requestedQoSs arrays 29 | * @param topicFilters - array of topic filter names 30 | * @param requestedQoSs - array of requested QoS 31 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 32 | * @param buflen the length in bytes of the data in the supplied buffer 33 | * @return the length of the serialized data. <= 0 indicates error 34 | */ 35 | int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[], 36 | int requestedQoSs[], unsigned char* buf, int buflen) 37 | { 38 | MQTTHeader header = {0}; 39 | unsigned char* curdata = buf; 40 | unsigned char* enddata = NULL; 41 | int rc = MQTTPACKET_READ_ERROR; 42 | int mylen = 0; 43 | 44 | FUNC_ENTRY; 45 | header.byte = readChar(&curdata); 46 | if (header.bits.type != SUBSCRIBE) 47 | goto exit; 48 | *dup = header.bits.dup; 49 | 50 | rc = MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */ 51 | if (rc <= 0) 52 | goto exit; 53 | curdata += rc; 54 | rc = MQTTPACKET_READ_ERROR; 55 | enddata = curdata + mylen; 56 | 57 | *packetid = readInt(&curdata); 58 | 59 | *count = 0; 60 | while (curdata < enddata) 61 | { 62 | if (*count == maxcount) 63 | goto exit; 64 | if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata)) 65 | goto exit; 66 | if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */ 67 | goto exit; 68 | requestedQoSs[*count] = readChar(&curdata); 69 | (*count)++; 70 | } 71 | 72 | rc = 1; 73 | exit: 74 | FUNC_EXIT_RC(rc); 75 | return rc; 76 | } 77 | 78 | 79 | /** 80 | * Serializes the supplied suback data into the supplied buffer, ready for sending 81 | * @param buf the buffer into which the packet will be serialized 82 | * @param buflen the length in bytes of the supplied buffer 83 | * @param packetid integer - the MQTT packet identifier 84 | * @param count - number of members in the grantedQoSs array 85 | * @param grantedQoSs - array of granted QoS 86 | * @return the length of the serialized data. <= 0 indicates error 87 | */ 88 | int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs) 89 | { 90 | MQTTHeader header = {0}; 91 | int rc = -1; 92 | unsigned char *ptr = buf; 93 | int i; 94 | 95 | FUNC_ENTRY; 96 | if (buflen < 2 + count) 97 | { 98 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 99 | goto exit; 100 | } 101 | header.byte = 0; 102 | header.bits.type = SUBACK; 103 | writeChar(&ptr, header.byte); /* write header */ 104 | 105 | ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */ 106 | 107 | writeInt(&ptr, packetid); 108 | 109 | for (i = 0; i < count; ++i) 110 | writeChar(&ptr, grantedQoSs[i]); 111 | 112 | rc = ptr - buf; 113 | exit: 114 | FUNC_EXIT_RC(rc); 115 | return rc; 116 | } 117 | 118 | 119 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTUnsubscribe.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Xiang Rong - 442039 Add makefile to Embedded C client 16 | *******************************************************************************/ 17 | 18 | #ifndef MQTTUNSUBSCRIBE_H_ 19 | #define MQTTUNSUBSCRIBE_H_ 20 | 21 | #if !defined(DLLImport) 22 | #define DLLImport 23 | #endif 24 | #if !defined(DLLExport) 25 | #define DLLExport 26 | #endif 27 | 28 | DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 29 | int count, MQTTString topicFilters[]); 30 | 31 | DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[], 32 | unsigned char* buf, int len); 33 | 34 | DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid); 35 | 36 | DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len); 37 | 38 | #endif /* MQTTUNSUBSCRIBE_H_ */ 39 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTUnsubscribeClient.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include "StackTrace.h" 19 | 20 | #include 21 | 22 | /** 23 | * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters 24 | * @param count the number of topic filter strings in topicFilters 25 | * @param topicFilters the array of topic filter strings to be used in the publish 26 | * @return the length of buffer needed to contain the serialized version of the packet 27 | */ 28 | int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[]) 29 | { 30 | int i; 31 | int len = 2; /* packetid */ 32 | 33 | for (i = 0; i < count; ++i) 34 | len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/ 35 | return len; 36 | } 37 | 38 | 39 | /** 40 | * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending 41 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 42 | * @param buflen the length in bytes of the data in the supplied buffer 43 | * @param dup integer - the MQTT dup flag 44 | * @param packetid integer - the MQTT packet identifier 45 | * @param count - number of members in the topicFilters array 46 | * @param topicFilters - array of topic filter names 47 | * @return the length of the serialized data. <= 0 indicates error 48 | */ 49 | int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, 50 | int count, MQTTString topicFilters[]) 51 | { 52 | unsigned char *ptr = buf; 53 | MQTTHeader header = {0}; 54 | int rem_len = 0; 55 | int rc = -1; 56 | int i = 0; 57 | 58 | FUNC_ENTRY; 59 | if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen) 60 | { 61 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 62 | goto exit; 63 | } 64 | 65 | header.byte = 0; 66 | header.bits.type = UNSUBSCRIBE; 67 | header.bits.dup = dup; 68 | header.bits.qos = 1; 69 | writeChar(&ptr, header.byte); /* write header */ 70 | 71 | ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */; 72 | 73 | writeInt(&ptr, packetid); 74 | 75 | for (i = 0; i < count; ++i) 76 | writeMQTTString(&ptr, topicFilters[i]); 77 | 78 | rc = ptr - buf; 79 | exit: 80 | FUNC_EXIT_RC(rc); 81 | return rc; 82 | } 83 | 84 | 85 | /** 86 | * Deserializes the supplied (wire) buffer into unsuback data 87 | * @param packetid returned integer - the MQTT packet identifier 88 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 89 | * @param buflen the length in bytes of the data in the supplied buffer 90 | * @return error code. 1 is success, 0 is failure 91 | */ 92 | int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen) 93 | { 94 | unsigned char type = 0; 95 | unsigned char dup = 0; 96 | int rc = 0; 97 | 98 | FUNC_ENTRY; 99 | rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen); 100 | if (type == UNSUBACK) 101 | rc = 1; 102 | FUNC_EXIT_RC(rc); 103 | return rc; 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /MQTTPacket/src/MQTTUnsubscribeServer.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | *******************************************************************************/ 16 | 17 | #include "MQTTPacket.h" 18 | #include "StackTrace.h" 19 | 20 | #include 21 | 22 | 23 | /** 24 | * Deserializes the supplied (wire) buffer into unsubscribe data 25 | * @param dup integer returned - the MQTT dup flag 26 | * @param packetid integer returned - the MQTT packet identifier 27 | * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays 28 | * @param count - number of members in the topicFilters and requestedQoSs arrays 29 | * @param topicFilters - array of topic filter names 30 | * @param buf the raw buffer data, of the correct length determined by the remaining length field 31 | * @param buflen the length in bytes of the data in the supplied buffer 32 | * @return the length of the serialized data. <= 0 indicates error 33 | */ 34 | int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[], 35 | unsigned char* buf, int len) 36 | { 37 | MQTTHeader header = {0}; 38 | unsigned char* curdata = buf; 39 | unsigned char* enddata = NULL; 40 | int rc = 0; 41 | int mylen = 0; 42 | 43 | FUNC_ENTRY; 44 | header.byte = readChar(&curdata); 45 | if (header.bits.type != UNSUBSCRIBE) 46 | goto exit; 47 | *dup = header.bits.dup; 48 | 49 | curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */ 50 | enddata = curdata + mylen; 51 | 52 | *packetid = readInt(&curdata); 53 | 54 | *count = 0; 55 | while (curdata < enddata) 56 | { 57 | if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata)) 58 | goto exit; 59 | (*count)++; 60 | } 61 | 62 | rc = 1; 63 | exit: 64 | FUNC_EXIT_RC(rc); 65 | return rc; 66 | } 67 | 68 | 69 | /** 70 | * Serializes the supplied unsuback data into the supplied buffer, ready for sending 71 | * @param buf the buffer into which the packet will be serialized 72 | * @param buflen the length in bytes of the supplied buffer 73 | * @param packetid integer - the MQTT packet identifier 74 | * @return the length of the serialized data. <= 0 indicates error 75 | */ 76 | int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid) 77 | { 78 | MQTTHeader header = {0}; 79 | int rc = 0; 80 | unsigned char *ptr = buf; 81 | 82 | FUNC_ENTRY; 83 | if (buflen < 2) 84 | { 85 | rc = MQTTPACKET_BUFFER_TOO_SHORT; 86 | goto exit; 87 | } 88 | header.byte = 0; 89 | header.bits.type = UNSUBACK; 90 | writeChar(&ptr, header.byte); /* write header */ 91 | 92 | ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */ 93 | 94 | writeInt(&ptr, packetid); 95 | 96 | rc = ptr - buf; 97 | exit: 98 | FUNC_EXIT_RC(rc); 99 | return rc; 100 | } 101 | 102 | 103 | -------------------------------------------------------------------------------- /MQTTPacket/src/StackTrace.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2014 IBM Corp. 3 | * 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License v1.0 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. 7 | * 8 | * The Eclipse Public License is available at 9 | * http://www.eclipse.org/legal/epl-v10.html 10 | * and the Eclipse Distribution License is available at 11 | * http://www.eclipse.org/org/documents/edl-v10.php. 12 | * 13 | * Contributors: 14 | * Ian Craggs - initial API and implementation and/or initial documentation 15 | * Ian Craggs - fix for bug #434081 16 | *******************************************************************************/ 17 | 18 | #ifndef STACKTRACE_H_ 19 | #define STACKTRACE_H_ 20 | 21 | #include 22 | #define NOSTACKTRACE 1 23 | 24 | #if defined(NOSTACKTRACE) 25 | #define FUNC_ENTRY 26 | #define FUNC_ENTRY_NOLOG 27 | #define FUNC_ENTRY_MED 28 | #define FUNC_ENTRY_MAX 29 | #define FUNC_EXIT 30 | #define FUNC_EXIT_NOLOG 31 | #define FUNC_EXIT_MED 32 | #define FUNC_EXIT_MAX 33 | #define FUNC_EXIT_RC(x) 34 | #define FUNC_EXIT_MED_RC(x) 35 | #define FUNC_EXIT_MAX_RC(x) 36 | 37 | #else 38 | 39 | #if defined(WIN32) 40 | #define inline __inline 41 | #define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM) 42 | #define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1) 43 | #define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM) 44 | #define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM) 45 | #define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM) 46 | #define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1) 47 | #define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM) 48 | #define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM) 49 | #define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM) 50 | #define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM) 51 | #define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM) 52 | #else 53 | #define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM) 54 | #define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1) 55 | #define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM) 56 | #define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM) 57 | #define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM) 58 | #define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1) 59 | #define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM) 60 | #define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM) 61 | #define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM) 62 | #define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM) 63 | #define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM) 64 | 65 | void StackTrace_entry(const char* name, int line, int trace); 66 | void StackTrace_exit(const char* name, int line, void* return_value, int trace); 67 | 68 | void StackTrace_printStack(FILE* dest); 69 | char* StackTrace_get(unsigned long); 70 | 71 | #endif 72 | 73 | #endif 74 | 75 | 76 | 77 | 78 | #endif /* STACKTRACE_H_ */ 79 | -------------------------------------------------------------------------------- /MQTTPacket/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(mqttpacket-tests) 2 | 3 | IF (WIN32) 4 | SET(MQTT_TEST_BROKER "tcp://mqtt.iotree.co.uk:1883" CACHE STRING "Hostname of a test MQTT broker to use") 5 | SET(MQTT_TEST_PROXY "tcp://localhost:1883" CACHE STRING "Hostname of the test proxy to use") 6 | SET(MQTT_SSL_HOSTNAME "mqtt.iotree.co.uk" CACHE STRING "Hostname of a test SSL MQTT broker to use") 7 | SET(CERTDIR $ENV{APPVEYOR_BUILD_FOLDER}/test/ssl) 8 | ELSE () 9 | SET(MQTT_TEST_BROKER "tcp://localhost:1883" CACHE STRING "Hostname of a test MQTT broker to use") 10 | SET(MQTT_TEST_PROXY "tcp://localhost:1884" CACHE STRING "Hostname of the test proxy to use") 11 | SET(MQTT_SSL_HOSTNAME "localhost" CACHE STRING "Hostname of a test SSL MQTT broker to use") 12 | SET(CERTDIR $ENV{TRAVIS_BUILD_DIR}/test/ssl) 13 | ENDIF () 14 | 15 | include_directories(../src) 16 | 17 | ADD_EXECUTABLE( 18 | test1 19 | test1.c 20 | ) 21 | 22 | TARGET_LINK_LIBRARIES( 23 | test1 24 | paho-embed-mqtt3c 25 | ) 26 | 27 | ADD_TEST( 28 | NAME test1 29 | COMMAND "test1" "--connection" ${MQTT_TEST_BROKER} 30 | ) 31 | 32 | SET_TESTS_PROPERTIES( 33 | test1 34 | PROPERTIES TIMEOUT 540 35 | ) 36 | -------------------------------------------------------------------------------- /MQTTPacket/test/build_test: -------------------------------------------------------------------------------- 1 | gcc -Wall test1.c -o test1 -I../src ../src/MQTTConnectClient.c ../src/MQTTConnectServer.c ../src/MQTTPacket.c ../src/MQTTSerializePublish.c ../src/MQTTDeserializePublish.c ../src/MQTTSubscribeServer.c ../src/MQTTSubscribeClient.c ../src/MQTTUnsubscribeServer.c ../src/MQTTUnsubscribeClient.c 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2009, 2014 IBM Corp. 3 | # 4 | # All rights reserved. This program and the accompanying materials 5 | # are made available under the terms of the Eclipse Public License v1.0 6 | # and Eclipse Distribution License v1.0 which accompany this distribution. 7 | # 8 | # The Eclipse Public License is available at 9 | # http://www.eclipse.org/legal/epl-v10.html 10 | # and the Eclipse Distribution License is available at 11 | # http://www.eclipse.org/org/documents/edl-v10.php. 12 | # 13 | # Contributors: 14 | # Xiang Rong - 442039 Add makefile to Embedded C client 15 | #*******************************************************************************/ 16 | 17 | # Note: on OS X you should install XCode and the associated command-line tools 18 | 19 | SHELL = /bin/sh 20 | .PHONY: clean, mkdir, install, uninstall, html 21 | 22 | # assume this is normally run in the main Paho directory 23 | ifndef srcdir 24 | srcdir = MQTTPacket/src 25 | endif 26 | 27 | ifndef blddir 28 | blddir = build/output 29 | endif 30 | 31 | ifndef prefix 32 | prefix = /usr/local 33 | endif 34 | 35 | ifndef exec_prefix 36 | exec_prefix = ${prefix} 37 | endif 38 | 39 | bindir = $(exec_prefix)/bin 40 | includedir = $(prefix)/include 41 | libdir = $(exec_prefix)/lib 42 | 43 | SOURCE_FILES_C = $(srcdir)/*.c 44 | 45 | HEADERS = $(srcdir)/*.h 46 | 47 | 48 | SAMPLE_FILES_C = pub0sub1 qos0pub 49 | SYNC_SAMPLES = ${addprefix ${blddir}/samples/,${SAMPLE_FILES_C}} 50 | 51 | 52 | TEST_FILES_C = test1 53 | SYNC_TESTS = ${addprefix ${blddir}/test/,${TEST_FILES_C}} 54 | 55 | 56 | # The names of libraries to be built 57 | MQTT_EMBED_LIB_C = paho-embed-mqtt3c 58 | 59 | 60 | # determine current platform 61 | ifeq ($(OS),Windows_NT) 62 | OSTYPE = $(OS) 63 | else 64 | OSTYPE = $(shell uname -s) 65 | MACHINETYPE = $(shell uname -m) 66 | endif 67 | 68 | ifeq ($(OSTYPE),Linux) 69 | 70 | CC ?= gcc 71 | 72 | ifndef INSTALL 73 | INSTALL = install 74 | endif 75 | INSTALL_PROGRAM = $(INSTALL) 76 | INSTALL_DATA = $(INSTALL) -m 644 77 | 78 | MAJOR_VERSION = 1 79 | MINOR_VERSION = 0 80 | VERSION = ${MAJOR_VERSION}.${MINOR_VERSION} 81 | 82 | EMBED_MQTTLIB_C_TARGET = ${blddir}/lib${MQTT_EMBED_LIB_C}.so.${VERSION} 83 | 84 | 85 | CCFLAGS_SO = -g -fPIC -Os -Wall -fvisibility=hidden -DLINUX_SO 86 | FLAGS_EXE = -I ${srcdir} -L ${blddir} 87 | 88 | LDFLAGS_C = -shared -Wl,-soname,lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} 89 | 90 | all: build 91 | 92 | build: | mkdir ${EMBED_MQTTLIB_C_TARGET} ${SYNC_SAMPLES} ${SYNC_TESTS} 93 | 94 | clean: 95 | rm -rf ${blddir}/* 96 | 97 | mkdir: 98 | -mkdir -p ${blddir}/samples 99 | -mkdir -p ${blddir}/test 100 | 101 | ${SYNC_TESTS}: ${blddir}/test/%: ${srcdir}/../test/%.c 102 | ${CC} -g -o ${blddir}/test/${basename ${+F}} $< -l${MQTT_EMBED_LIB_C} ${FLAGS_EXE} 103 | 104 | 105 | ${SYNC_SAMPLES}: ${blddir}/samples/%: ${srcdir}/../samples/%.c ${srcdir}/../samples/transport.o 106 | ${CC} -o $@ $^ -l${MQTT_EMBED_LIB_C} ${FLAGS_EXE} 107 | 108 | 109 | 110 | ${EMBED_MQTTLIB_C_TARGET}: ${SOURCE_FILES_C} ${HEADERS_C} 111 | ${CC} ${CCFLAGS_SO} -o $@ ${SOURCE_FILES_C} ${LDFLAGS_C} 112 | -ln -s lib$(MQTT_EMBED_LIB_C).so.${VERSION} ${blddir}/lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} 113 | -ln -s lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} ${blddir}/lib$(MQTT_EMBED_LIB_C).so 114 | 115 | 116 | strip_options: 117 | $(eval INSTALL_OPTS := -s) 118 | 119 | install-strip: build strip_options install 120 | 121 | install: build 122 | $(INSTALL_DATA) ${INSTALL_OPTS} ${EMBED_MQTTLIB_C_TARGET} $(DESTDIR)${libdir} 123 | 124 | 125 | /sbin/ldconfig $(DESTDIR)${libdir} 126 | ln -s lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so 127 | 128 | 129 | uninstall: 130 | rm $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so.${VERSION} 131 | 132 | /sbin/ldconfig $(DESTDIR)${libdir} 133 | rm $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so 134 | 135 | 136 | html: 137 | 138 | ARDUINO_LIB_FILES = MQTTClient/src/*.h MQTTClient/src/arduino/*.h $(srcdir)/* 139 | ARDUINO_SAMPLES = MQTTClient/samples/arduino/* 140 | LEGAL_FILES = edl-v10 epl-v10 notice.html about.html CONTRIBUTING.md README.md library.properties 141 | 142 | arduino: mkdir 143 | -mkdir -p ${blddir}/arduino/MQTTClient/examples 144 | -mkdir -p ${blddir}/arduino/MQTTClient/src 145 | cp $(ARDUINO_LIB_FILES) ${blddir}/arduino/MQTTClient/src 146 | cp $(LEGAL_FILES) ${blddir}/arduino/MQTTClient 147 | cp -R $(ARDUINO_SAMPLES) ${blddir}/arduino/MQTTClient/examples 148 | cd ${blddir}/arduino && zip -r arduino MQTTClient 149 | 150 | endif 151 | 152 | 153 | 154 | ifeq ($(OSTYPE),Darwin) 155 | 156 | CC ?= gcc 157 | 158 | ifndef INSTALL 159 | INSTALL = install 160 | endif 161 | INSTALL_PROGRAM = $(INSTALL) 162 | INSTALL_DATA = $(INSTALL) -m 644 163 | 164 | MAJOR_VERSION = 1 165 | MINOR_VERSION = 0 166 | VERSION = ${MAJOR_VERSION}.${MINOR_VERSION} 167 | 168 | EMBED_MQTTLIB_C_TARGET = ${blddir}/lib${MQTT_EMBED_LIB_C}.so.${VERSION} 169 | 170 | 171 | CCFLAGS_SO = -g -fPIC -Os -Wall -fvisibility=hidden -Wno-deprecated-declarations -DUSE_NAMED_SEMAPHORES 172 | FLAGS_EXE = -I ${srcdir} -L ${blddir} 173 | 174 | LDFLAGS_C = -shared -Wl,-install_name,lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} 175 | 176 | all: build 177 | 178 | build: | mkdir ${EMBED_MQTTLIB_C_TARGET} ${SYNC_SAMPLES} ${SYNC_TESTS} 179 | 180 | clean: 181 | rm -rf ${blddir}/* 182 | 183 | mkdir: 184 | -mkdir -p ${blddir}/samples 185 | -mkdir -p ${blddir}/test 186 | 187 | ${SYNC_TESTS}: ${blddir}/test/%: ${srcdir}/../test/%.c 188 | ${CC} -g -o ${blddir}/test/${basename ${+F}} $< -l${MQTT_EMBED_LIB_C} ${FLAGS_EXE} 189 | 190 | ${SYNC_SAMPLES}: ${blddir}/samples/%: ${srcdir}/../samples/%.c 191 | ${CC} -o ${blddir}/samples/${basename ${+F}} $< ${FLAGS_EXE} -l${MQTT_EMBED_LIB_C} 192 | 193 | ${EMBED_MQTTLIB_C_TARGET}: ${SOURCE_FILES_C} ${HEADERS_C} 194 | ${CC} ${CCFLAGS_SO} -o $@ ${SOURCE_FILES_C} ${LDFLAGS_C} 195 | -ln -s lib$(MQTT_EMBED_LIB_C).so.${VERSION} ${blddir}/lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} 196 | -ln -s lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} ${blddir}/lib$(MQTT_EMBED_LIB_C).so 197 | 198 | 199 | strip_options: 200 | $(eval INSTALL_OPTS := -s) 201 | 202 | install-strip: build strip_options install 203 | 204 | install: build 205 | $(INSTALL_DATA) ${INSTALL_OPTS} ${EMBED_MQTTLIB_C_TARGET} $(DESTDIR)${libdir} 206 | 207 | /sbin/ldconfig $(DESTDIR)${libdir} 208 | ln -s lib$(MQTT_EMBED_LIB_C).so.${MAJOR_VERSION} $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so 209 | 210 | 211 | uninstall: 212 | rm $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so.${VERSION} 213 | /sbin/ldconfig $(DESTDIR)${libdir} 214 | rm $(DESTDIR)${libdir}/lib$(MQTT_EMBED_LIB_C).so 215 | 216 | 217 | html: 218 | 219 | 220 | endif 221 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | # Notices for Eclipse Paho 2 | 3 | This content is produced and maintained by the Eclipse Paho project. 4 | 5 | * Project home: https://projects.eclipse.org/projects/iot.paho 6 | 7 | ## Trademarks 8 | 9 | Paho™ is a trademark of the Eclipse Foundation. 10 | 11 | ## Copyright 12 | 13 | All content is the property of the respective authors or their employers. For 14 | more information regarding authorship of content, please consult the listed 15 | source code repository logs. 16 | 17 | ## Declared Project Licenses 18 | 19 | This program and the accompanying materials are made available under the terms 20 | of the Eclipse Public License v2.0 which is available at 21 | https://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 22 | v1.0 which is available at https://www.eclipse.org/org/documents/edl-v10.php. 23 | 24 | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause 25 | 26 | ## Source Code 27 | 28 | The project maintains the following source code repositories: 29 | 30 | * https://github.com/eclipse/paho-website 31 | * https://github.com/eclipse/paho.golang 32 | * https://github.com/eclipse/paho.mqtt-sn.embedded-c 33 | * https://github.com/eclipse/paho.mqtt-spy 34 | * https://github.com/eclipse/paho.mqtt.android 35 | * https://github.com/eclipse/paho.mqtt.c 36 | * https://github.com/eclipse/paho.mqtt.cpp 37 | * https://github.com/eclipse/paho.mqtt.d 38 | * https://github.com/eclipse/paho.mqtt.embedded-c 39 | * https://github.com/eclipse/paho.mqtt.golang 40 | * https://github.com/eclipse/paho.mqtt.java 41 | * https://github.com/eclipse/paho.mqtt.javascript 42 | * https://github.com/eclipse/paho.mqtt.m2mqtt 43 | * https://github.com/eclipse/paho.mqtt.python 44 | * https://github.com/eclipse/paho.mqtt.ruby 45 | * https://github.com/eclipse/paho.mqtt.rust 46 | * https://github.com/eclipse/paho.mqtt.testing 47 | 48 | ## Cryptography 49 | 50 | Content may contain encryption software. The country in which you are currently 51 | may have restrictions on the import, possession, and use, and/or re-export to 52 | another country, of encryption software. BEFORE using any encryption software, 53 | please check the country's laws, regulations and policies concerning the import, 54 | possession, or use, and re-export of encryption software, to see if this is 55 | permitted. 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eclipse Paho MQTT C/C++ client for Embedded platforms 2 | 3 | This repository contains the source code for the [Eclipse Paho](http://eclipse.org/paho) MQTT C/C++ client library for Embedded platorms. 4 | 5 | It is dual licensed under the EPL and EDL (see about.html and notice.html for more details). You can choose which of these licenses you want to use the code under. The EDL allows you to embed the code into your application, and distribute your application in binary or source form without contributing any of your code, or any changes you make back to Paho. See the EDL for the exact conditions. 6 | 7 | There are three sub-projects: 8 | 9 | 1. MQTTPacket - simple de/serialization of MQTT packets, plus helper functions 10 | 2. MQTTClient - high(er) level C++ client, plus 11 | 3. MQTTClient-C - high(er) level C client (pretty much a clone of the C++ client) 12 | 13 | The *MQTTPacket* directory contains the lowest level C library with the smallest requirements. This supplies simple serialization 14 | and deserialization routines. They serve as a base for the higher level libraries, but can also be used on their own 15 | It is mainly up to you to write and read to and from the network. 16 | 17 | The *MQTTClient* directory contains the next level C++ library. This networking code is contained in separate classes so that you can plugin the 18 | network of your choice. Currently there are implementations for Linux, Arduino and mbed. ARM mbed was the first platform for which this was written, 19 | where the conventional language choice is C++, which explains the language choice. I have written a starter [Porting Guide](http://modelbasedtesting.co.uk/2014/08/25/porting-a-paho-embedded-c-client/). 20 | 21 | The *MQTTClient-C* directory contains a C equivalent of MQTTClient, for those platforms where C++ is not supported or the convention. As far 22 | as possible it is a direct translation from *MQTTClient*. 23 | 24 | ## Build requirements / compilation 25 | 26 | CMake builds for the various packages have been introduced, along with Travis-CI configuration for automated build & testing. The basic 27 | method of building on Linux is: 28 | 29 | ``` 30 | mkdir build.paho 31 | cd build.paho 32 | cmake .. 33 | make 34 | ``` 35 | 36 | The travis-build.sh file has the full build and test sequence for Linux. 37 | 38 | 39 | ## Usage and API 40 | 41 | See the samples directories for examples of intended use. Doxygen config files for each package are available in the doc directory. 42 | 43 | ## Runtime tracing 44 | 45 | The *MQTTClient* API has debug tracing for MQTT packets sent and received - turn this on by setting the MQTT_DEBUG preprocessor definition. 46 | 47 | 48 | ## Reporting bugs 49 | 50 | This project uses GitHub Issues here: [github.com/eclipse/paho.mqtt.embedded-c/issues](https://github.com/eclipse/paho.mqtt.embedded-c/issues) to track ongoing development and issues. 51 | 52 | ## More information 53 | 54 | Discussion of the Paho clients takes place on the [Eclipse Mattermost Paho channel](https://mattermost.eclipse.org/eclipse/channels/paho) and the [Eclipse paho-dev mailing list](https://dev.eclipse.org/mailman/listinfo/paho-dev). 55 | 56 | General questions about the MQTT protocol are discussed in the [MQTT Google Group](https://groups.google.com/forum/?hl=en-US&fromgroups#!forum/mqtt). 57 | 58 | More information is available via the [MQTT community](http://mqtt.org). 59 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | This project follows the [Eclipse Vulnerability Reporting Policy](https://www.eclipse.org/security/policy.php). 4 | Vulnerabilities are tracked by the Eclipse security team, in cooperation with the project lead. 5 | Fixing vulnerabilities is taken care of by the project committers, with assistance and guidance of the security 6 | team. 7 | 8 | ## Supported Versions 9 | 10 | Eclipse Paho provides security updates for the most recent version only. 11 | 12 | ## Reporting a Vulnerability 13 | 14 | We recommend that in case of suspected vulnerabilities you do not create a GitHub issue, but instead contact the 15 | Eclipse Security Team directly sending an email to security@eclipse.org. 16 | 17 | -------------------------------------------------------------------------------- /about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | About 5 | 6 | 7 |

About This Content

8 | 9 |

December 9, 2013

10 |

License

11 | 12 |

The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise 13 | indicated below, the Content is provided to you under the terms and conditions of the 14 | Eclipse Public License Version 1.0 ("EPL") and Eclipse Distribution License Version 1.0 ("EDL"). 15 | A copy of the EPL is available at 16 | http://www.eclipse.org/legal/epl-v10.html 17 | and a copy of the EDL is available at 18 | http://www.eclipse.org/org/documents/edl-v10.php. 19 | For purposes of the EPL, "Program" will mean the Content.

20 | 21 |

If you did not receive this Content directly from the Eclipse Foundation, the Content is 22 | being redistributed by another party ("Redistributor") and different terms and conditions may 23 | apply to your use of any object code in the Content. Check the Redistributor's license that was 24 | provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise 25 | indicated below, the terms and conditions of the EPL still apply to any source code in the Content 26 | and such source code may be obtained at http://www.eclipse.org.

27 | 28 | 29 | -------------------------------------------------------------------------------- /doc/pahologo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-paho/paho.mqtt.embedded-c/32ad8d0d19ac982e32f5f4358adc00e5511ecff5/doc/pahologo.png -------------------------------------------------------------------------------- /edl-v10: -------------------------------------------------------------------------------- 1 | 2 | Eclipse Distribution License - v 1.0 3 | 4 | Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 9 | 10 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 11 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 12 | Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 15 | 16 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=MQTTClient 2 | version=1.0.0 3 | author=Ian Craggs 4 | maintainer=Ian Craggs https://github.com/icraggs 5 | sentence=This is the lowest level library, the simplest and smallest, but hardest to use. It simply deals with serialization and deserialization of MQTT packets. 6 | paragraph=... 7 | category=Communication 8 | url=https://github.com/eclipse/paho.mqtt.embedded-c 9 | architectures=* 10 | -------------------------------------------------------------------------------- /test/mqttsas.py: -------------------------------------------------------------------------------- 1 | """ 2 | ******************************************************************* 3 | Copyright (c) 2013, 2018 IBM Corp. 4 | 5 | All rights reserved. This program and the accompanying materials 6 | are made available under the terms of the Eclipse Public License v1.0 7 | and Eclipse Distribution License v1.0 which accompany this distribution. 8 | 9 | The Eclipse Public License is available at 10 | http://www.eclipse.org/legal/epl-v10.html 11 | and the Eclipse Distribution License is available at 12 | http://www.eclipse.org/org/documents/edl-v10.php. 13 | 14 | Contributors: 15 | Ian Craggs - initial implementation and/or documentation 16 | Ian Craggs - add MQTTV5 support 17 | ******************************************************************* 18 | """ 19 | from __future__ import print_function 20 | 21 | import socket, sys, select, traceback, datetime, os 22 | try: 23 | import socketserver 24 | import MQTTV311 # Trace MQTT traffic - Python 3 version 25 | import MQTTV5 26 | except: 27 | traceback.print_exc() 28 | import SocketServer as socketserver 29 | import MQTTV3112 as MQTTV311 # Trace MQTT traffic - Python 2 version 30 | import MQTTV5 31 | 32 | MQTT = MQTTV311 33 | logging = True 34 | myWindow = None 35 | 36 | 37 | def timestamp(): 38 | now = datetime.datetime.now() 39 | return now.strftime('%Y%m%d %H%M%S')+str(float("."+str(now.microsecond)))[1:] 40 | 41 | suspended = [] 42 | 43 | class MyHandler(socketserver.StreamRequestHandler): 44 | 45 | def handle(self): 46 | global MQTT 47 | if not hasattr(self, "ids"): 48 | self.ids = {} 49 | if not hasattr(self, "versions"): 50 | self.versions = {} 51 | inbuf = True 52 | i = o = e = None 53 | try: 54 | clients = self.request 55 | brokers = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 56 | brokers.connect((brokerhost, brokerport)) 57 | terminated = False 58 | while inbuf != None and not terminated: 59 | (i, o, e) = select.select([clients, brokers], [], []) 60 | for s in i: 61 | if s in suspended: 62 | print("suspended") 63 | if s == clients and s not in suspended: 64 | inbuf = MQTT.getPacket(clients) # get one packet 65 | if inbuf == None: 66 | break 67 | try: 68 | # if connect, this could be MQTTV3 or MQTTV5 69 | if inbuf[0] >> 4 == 1: # connect packet 70 | protocol_string = b'MQTT' 71 | pos = inbuf.find(protocol_string) 72 | if pos != -1: 73 | version = inbuf[pos + len(protocol_string)] 74 | if version == 5: 75 | MQTT = MQTTV5 76 | else: 77 | MQTT = MQTTV311 78 | packet = MQTT.unpackPacket(inbuf) 79 | if hasattr(packet.fh, "MessageType"): 80 | packet_type = packet.fh.MessageType 81 | publish_type = MQTT.PUBLISH 82 | connect_type = MQTT.CONNECT 83 | else: 84 | packet_type = packet.fh.PacketType 85 | publish_type = MQTT.PacketTypes.PUBLISH 86 | connect_type = MQTT.PacketTypes.CONNECT 87 | if packet_type == publish_type and \ 88 | packet.topicName == "MQTTSAS topic" and \ 89 | packet.data == b"TERMINATE": 90 | print("Terminating client", self.ids[id(clients)]) 91 | brokers.close() 92 | clients.close() 93 | terminated = True 94 | break 95 | elif packet_type == publish_type and \ 96 | packet.topicName == "MQTTSAS topic" and \ 97 | packet.data == b"TERMINATE_SERVER": 98 | print("Suspending client ", self.ids[id(clients)]) 99 | suspended.append(clients) 100 | elif packet_type == connect_type: 101 | self.ids[id(clients)] = packet.ClientIdentifier 102 | self.versions[id(clients)] = 3 103 | print(timestamp() , "C to S", self.ids[id(clients)], str(packet)) 104 | #print([hex(b) for b in inbuf]) 105 | #print(inbuf) 106 | except: 107 | traceback.print_exc() 108 | brokers.send(inbuf) # pass it on 109 | elif s == brokers: 110 | inbuf = MQTT.getPacket(brokers) # get one packet 111 | if inbuf == None: 112 | break 113 | try: 114 | print(timestamp(), "S to C", self.ids[id(clients)], str(MQTT.unpackPacket(inbuf))) 115 | except: 116 | traceback.print_exc() 117 | clients.send(inbuf) 118 | print(timestamp()+" client "+self.ids[id(clients)]+" connection closing") 119 | except: 120 | print(repr((i, o, e)), repr(inbuf)) 121 | traceback.print_exc() 122 | if id(clients) in self.ids.keys(): 123 | del self.ids[id(clients)] 124 | elif id(clients) in self.versions.keys(): 125 | del self.versions[id(clients)] 126 | 127 | class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 128 | pass 129 | 130 | def run(): 131 | global brokerhost, brokerport 132 | myhost = '127.0.0.1' 133 | if len(sys.argv) > 1: 134 | brokerhost = sys.argv[1] 135 | else: 136 | brokerhost = '127.0.0.1' 137 | 138 | if len(sys.argv) > 2: 139 | brokerport = int(sys.argv[2]) 140 | else: 141 | brokerport = 1883 142 | 143 | if len(sys.argv) > 3: 144 | myport = int(sys.argv[3]) 145 | else: 146 | if brokerhost == myhost: 147 | myport = brokerport + 1 148 | else: 149 | myport = 1883 150 | 151 | print("Listening on port", str(myport)+", broker on port", brokerport) 152 | s = ThreadingTCPServer(("127.0.0.1", myport), MyHandler) 153 | s.serve_forever() 154 | 155 | if __name__ == "__main__": 156 | run() 157 | -------------------------------------------------------------------------------- /test/mqttsas2.py: -------------------------------------------------------------------------------- 1 | """ 2 | ******************************************************************* 3 | Copyright (c) 2013, 2017 IBM Corp. 4 | 5 | All rights reserved. This program and the accompanying materials 6 | are made available under the terms of the Eclipse Public License v1.0 7 | and Eclipse Distribution License v1.0 which accompany this distribution. 8 | 9 | The Eclipse Public License is available at 10 | http://www.eclipse.org/legal/epl-v10.html 11 | and the Eclipse Distribution License is available at 12 | http://www.eclipse.org/org/documents/edl-v10.php. 13 | 14 | Contributors: 15 | Ian Craggs - initial implementation and/or documentation 16 | ******************************************************************* 17 | """ 18 | from __future__ import print_function 19 | 20 | # Trace MQTT traffic 21 | import MQTTV3112 as MQTTV3 22 | 23 | import socket, sys, select, traceback, datetime, os 24 | import SocketServer as socketserver 25 | 26 | logging = True 27 | myWindow = None 28 | 29 | 30 | def timestamp(): 31 | now = datetime.datetime.now() 32 | return now.strftime('%Y%m%d %H%M%S')+str(float("."+str(now.microsecond)))[1:] 33 | 34 | 35 | class MyHandler(socketserver.StreamRequestHandler): 36 | 37 | def handle(self): 38 | if not hasattr(self, "ids"): 39 | self.ids = {} 40 | if not hasattr(self, "versions"): 41 | self.versions = {} 42 | inbuf = True 43 | i = o = e = None 44 | try: 45 | clients = self.request 46 | brokers = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 47 | brokers.connect((brokerhost, brokerport)) 48 | terminated = False 49 | while inbuf != None and not terminated: 50 | (i, o, e) = select.select([clients, brokers], [], []) 51 | for s in i: 52 | if s == clients: 53 | inbuf = MQTTV3.getPacket(clients) # get one packet 54 | if inbuf == None: 55 | break 56 | try: 57 | packet = MQTTV3.unpackPacket(inbuf) 58 | if packet.fh.MessageType == MQTTV3.PUBLISH and \ 59 | packet.topicName == "MQTTSAS topic" and \ 60 | packet.data == b"TERMINATE": 61 | print("Terminating client", self.ids[id(clients)]) 62 | brokers.close() 63 | clients.close() 64 | terminated = True 65 | break 66 | elif packet.fh.MessageType == MQTTV3.CONNECT: 67 | self.ids[id(clients)] = packet.ClientIdentifier 68 | self.versions[id(clients)] = 3 69 | print(timestamp() , "C to S", self.ids[id(clients)], repr(packet)) 70 | #print([hex(b) for b in inbuf]) 71 | #print(inbuf) 72 | except: 73 | traceback.print_exc() 74 | brokers.send(inbuf) # pass it on 75 | elif s == brokers: 76 | inbuf = MQTTV3.getPacket(brokers) # get one packet 77 | if inbuf == None: 78 | break 79 | try: 80 | print(timestamp(), "S to C", self.ids[id(clients)], repr(MQTTV3.unpackPacket(inbuf))) 81 | except: 82 | traceback.print_exc() 83 | clients.send(inbuf) 84 | print(timestamp()+" client "+self.ids[id(clients)]+" connection closing") 85 | except: 86 | print(repr((i, o, e)), repr(inbuf)) 87 | traceback.print_exc() 88 | if id(clients) in self.ids.keys(): 89 | del self.ids[id(clients)] 90 | elif id(clients) in self.versions.keys(): 91 | del self.versions[id(clients)] 92 | 93 | class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 94 | pass 95 | 96 | def run(): 97 | global brokerhost, brokerport 98 | myhost = '127.0.0.1' 99 | if len(sys.argv) > 1: 100 | brokerhost = sys.argv[1] 101 | else: 102 | brokerhost = '127.0.0.1' 103 | 104 | if len(sys.argv) > 2: 105 | brokerport = int(sys.argv[2]) 106 | else: 107 | brokerport = 1883 108 | 109 | if len(sys.argv) > 3: 110 | myport = int(sys.argv[3]) 111 | else: 112 | if brokerhost == myhost: 113 | myport = brokerport + 1 114 | else: 115 | myport = 1883 116 | 117 | print("Listening on port", str(myport)+", broker on port", brokerport) 118 | s = ThreadingTCPServer(("127.0.0.1", myport), MyHandler) 119 | s.serve_forever() 120 | 121 | if __name__ == "__main__": 122 | run() 123 | -------------------------------------------------------------------------------- /travis-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | rm -rf build.paho 6 | mkdir build.paho 7 | cd build.paho 8 | echo "travis build dir $TRAVIS_BUILD_DIR pwd $PWD" 9 | cmake .. 10 | make 11 | python3 ../test/mqttsas.py localhost 1883 1885 & 12 | ctest -VV --timeout 600 13 | kill %1 14 | #killall mosquitto 15 | -------------------------------------------------------------------------------- /travis-env-vars: -------------------------------------------------------------------------------- 1 | export TRAVIS_OS_NAME=linux 2 | export TRAVIS_BUILD_DIR=/home/icraggs/git/paho.mqtt.embedded-c 3 | -------------------------------------------------------------------------------- /travis-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$TRAVIS_OS_NAME" == "linux" ]; then 4 | pwd 5 | sudo service mosquitto stop 6 | # Stop any mosquitto instance which may be still running from previous runs 7 | killall mosquitto 8 | mosquitto -h 9 | mosquitto & 10 | fi 11 | 12 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then 13 | pwd 14 | brew update 15 | brew install openssl mosquitto 16 | brew services stop mosquitto 17 | /usr/local/sbin/mosquitto -h 18 | /usr/local/sbin/mosquitto & 19 | fi 20 | --------------------------------------------------------------------------------