From 3ecb731c2322f3d83cdcdaedb8731fe7eb231b68 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 21 Jan 2020 16:44:02 +0100 Subject: [PATCH] mqtt: example test to check connection with different ssl parameters --- .../mqtt/weekend_test/mqtt_publish_test.py | 8 +- .../mqtt/publish_connect_test/CMakeLists.txt | 19 ++ .../Makefile | 2 +- .../README.md | 2 +- .../mqtt/publish_connect_test/ca.crt | 22 ++ .../mqtt/publish_connect_test/ca.der | Bin 0 -> 919 bytes .../mqtt/publish_connect_test/ca.key | 27 ++ .../mqtt/publish_connect_test/client_inv.crt | 19 ++ .../publish_connect_test/client_no_pwd.key | 27 ++ .../mqtt/publish_connect_test/client_pwd.crt | 18 ++ .../mqtt/publish_connect_test/client_pwd.key | 30 +++ .../mqtt/publish_connect_test/example_test.py | 230 +++++++++++++++++ .../publish_connect_test/main/CMakeLists.txt | 2 + .../main/Kconfig.projbuild | 35 +++ .../publish_connect_test/main/component.mk | 1 + .../publish_connect_test/main/connect_test.c | 237 ++++++++++++++++++ .../main/mqtt_eclipse_org.pem | 0 .../main/publish_connect_test.c | 76 ++++++ .../publish_connect_test/main/publish_test.c | 175 +++++++++++++ .../sdkconfig.ci | 0 .../sdkconfig.qemu | 0 .../mqtt/publish_connect_test/server.key | 27 ++ .../mqtt/publish_test/CMakeLists.txt | 13 - .../mqtt/publish_test/main/CMakeLists.txt | 2 - .../mqtt/publish_test/main/component.mk | 1 - .../mqtt/publish_test/main/publish_test.c | 226 ----------------- 26 files changed, 948 insertions(+), 251 deletions(-) create mode 100644 examples/protocols/mqtt/publish_connect_test/CMakeLists.txt rename examples/protocols/mqtt/{publish_test => publish_connect_test}/Makefile (85%) rename examples/protocols/mqtt/{publish_test => publish_connect_test}/README.md (98%) create mode 100644 examples/protocols/mqtt/publish_connect_test/ca.crt create mode 100644 examples/protocols/mqtt/publish_connect_test/ca.der create mode 100644 examples/protocols/mqtt/publish_connect_test/ca.key create mode 100644 examples/protocols/mqtt/publish_connect_test/client_inv.crt create mode 100644 examples/protocols/mqtt/publish_connect_test/client_no_pwd.key create mode 100644 examples/protocols/mqtt/publish_connect_test/client_pwd.crt create mode 100644 examples/protocols/mqtt/publish_connect_test/client_pwd.key create mode 100644 examples/protocols/mqtt/publish_connect_test/example_test.py create mode 100644 examples/protocols/mqtt/publish_connect_test/main/CMakeLists.txt rename examples/protocols/mqtt/{publish_test => publish_connect_test}/main/Kconfig.projbuild (63%) create mode 100644 examples/protocols/mqtt/publish_connect_test/main/component.mk create mode 100644 examples/protocols/mqtt/publish_connect_test/main/connect_test.c rename examples/protocols/mqtt/{publish_test => publish_connect_test}/main/mqtt_eclipse_org.pem (100%) create mode 100644 examples/protocols/mqtt/publish_connect_test/main/publish_connect_test.c create mode 100644 examples/protocols/mqtt/publish_connect_test/main/publish_test.c rename examples/protocols/mqtt/{publish_test => publish_connect_test}/sdkconfig.ci (100%) rename examples/protocols/mqtt/{publish_test => publish_connect_test}/sdkconfig.qemu (100%) create mode 100644 examples/protocols/mqtt/publish_connect_test/server.key delete mode 100644 examples/protocols/mqtt/publish_test/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/publish_test/main/CMakeLists.txt delete mode 100644 examples/protocols/mqtt/publish_test/main/component.mk delete mode 100644 examples/protocols/mqtt/publish_test/main/publish_test.c diff --git a/components/mqtt/weekend_test/mqtt_publish_test.py b/components/mqtt/weekend_test/mqtt_publish_test.py index 32ae3389f2..e018ebf24f 100644 --- a/components/mqtt/weekend_test/mqtt_publish_test.py +++ b/components/mqtt/weekend_test/mqtt_publish_test.py @@ -2,7 +2,6 @@ from __future__ import print_function from __future__ import unicode_literals from builtins import str import re -import os import sys import ssl import paho.mqtt.client as mqtt @@ -128,12 +127,7 @@ def test_weekend_mqtt_publish(env, extra_data): 3. Test evaluates python client received correct qos0 message 4. Test ESP32 client received correct qos0 message """ - dut1 = env.get_dut("mqtt_publish", "examples/protocols/mqtt/publish_test") - # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "mqtt_publish.bin") - bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("mqtt_publish_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("mqtt_publish_size", bin_size // 1024) + dut1 = env.get_dut("mqtt_publish_connect_test", "examples/protocols/mqtt/publish_connect_test") # Look for host:port in sdkconfig try: # python client subscribes to the topic to which esp client publishes and vice versa diff --git a/examples/protocols/mqtt/publish_connect_test/CMakeLists.txt b/examples/protocols/mqtt/publish_connect_test/CMakeLists.txt new file mode 100644 index 0000000000..6d1ef5af8f --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/CMakeLists.txt @@ -0,0 +1,19 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(mqtt_publish_connect_test) + +target_add_binary_data(mqtt_publish_connect_test.elf "main/mqtt_eclipse_org.pem" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "ca.crt" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "ca.der" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.key" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "client_pwd.crt" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "client_no_pwd.key" TEXT) +target_add_binary_data(mqtt_publish_connect_test.elf "client_inv.crt" TEXT) diff --git a/examples/protocols/mqtt/publish_test/Makefile b/examples/protocols/mqtt/publish_connect_test/Makefile similarity index 85% rename from examples/protocols/mqtt/publish_test/Makefile rename to examples/protocols/mqtt/publish_connect_test/Makefile index 7d552c3be2..49c193dd36 100644 --- a/examples/protocols/mqtt/publish_test/Makefile +++ b/examples/protocols/mqtt/publish_connect_test/Makefile @@ -2,7 +2,7 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := mqtt_publish +PROJECT_NAME := mqtt_publish_connect_test EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common diff --git a/examples/protocols/mqtt/publish_test/README.md b/examples/protocols/mqtt/publish_connect_test/README.md similarity index 98% rename from examples/protocols/mqtt/publish_test/README.md rename to examples/protocols/mqtt/publish_connect_test/README.md index ee377d5a64..2147420a55 100644 --- a/examples/protocols/mqtt/publish_test/README.md +++ b/examples/protocols/mqtt/publish_connect_test/README.md @@ -1,4 +1,4 @@ -# ESP-MQTT advanced published test +# ESP-MQTT advanced publish and connect test project (See the README.md file in the upper level 'examples' directory for more information about examples.) Main purpose of this example is to test the MQTT library to correctly publish and receive messages (of different size and sequences) over different transports. diff --git a/examples/protocols/mqtt/publish_connect_test/ca.crt b/examples/protocols/mqtt/publish_connect_test/ca.crt new file mode 100644 index 0000000000..894f2959b0 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDkzCCAnugAwIBAgIUNI5wldYysh6rtCzYmda6H414aRswDQYJKoZIhvcNAQEL +BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJRXNwcmVzc2lmMB4X +DTIwMDEyMTA5MDk0NloXDTI1MDEyMDA5MDk0NlowWTELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDESMBAGA1UEAwwJRXNwcmVzc2lmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAyadSpRnIQBVbEAsbpkrKrOMlBOMIUmA8AfNyOYPLfv0Oa5lBiMAV +3OQDu5tYyFYKwkCUqq65iAm50fPbSH71w1tkja6nZ1yAIM+TvpMlM/WiFGrhY+Tc +kAcLcKUJyPxrv/glzoVslbqUgIhuhCSKA8uk1+ILcn3nWzPcbcowLx31+AHeZj8h +bIAdj6vjqxMCFStp4IcA+ikmCk75LCN4vkkifdkebb/ZDNYCZZhpCBnCHyFAjPc4 +7C+FDVGT3/UUeeTy+Mtn+MqUAhB+W0sPDm1n2h59D4Z/MFm0hl6GQCAKeMJPzssU +BBsRm6zoyPQ4VTqG0uwfNNbORyIfKONMUwIDAQABo1MwUTAdBgNVHQ4EFgQUGYLV +EkgWzxjpltE6texha7zZVxowHwYDVR0jBBgwFoAUGYLVEkgWzxjpltE6texha7zZ +VxowDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAb2EF4Zg2XWNb +eZHnzupCDd9jAhwPqkt7F1OXvxJa/RFUSB9+2izGvikGGhuKY4f0iLuqF+bhExD9 +sapDcdFO2Suh4J3onbwEvmKvsv56K3xhapYg8WwPofpkVirnkwFjpQXGzrYxPujg +BPmSy3psQrhvOr/WH7SefJv2qr4ikaugfE+3enY4PL+C1dSQAuNo1QGgWsZIu0c8 +TZybNZ13vNVMA+tgj2CM8FR3Etaabwtu3TTcAnO7aoBTix/bLBTuZoczhN8/MhG3 +GylmDzFI8a6aKxQL3Fi4PsM82hRKWu3gfs39sR1Ci4V22v8uO5EWBPK0QZvDSc1a +KwwxI4zA0w== +-----END CERTIFICATE----- diff --git a/examples/protocols/mqtt/publish_connect_test/ca.der b/examples/protocols/mqtt/publish_connect_test/ca.der new file mode 100644 index 0000000000000000000000000000000000000000..c5c3304e23747ca8143d9d92365c99ac752799ff GIT binary patch literal 919 zcmXqLVxDZ!#8kb2nTe5!NyMbDVCpraO>(QZ=-iljZI^s+MW(a?FB_*;n@8JsUPeZ4 zRtAGeLv903Hs(+kHen{mP(xt@K@f+7hbuTgH&r*dB(WsbP|-jhB*?`h;h9>9lVs zq7a^$lAc*otPoIAso+zRVkl%F08+xt!|7UFP?TC+oS9}IC(dhRU|?uuXkckzX<`;7 z&TC|9U}$6j<k210{FgG#sGZ-{6axpbAGBTW89<)^Qgo9|b0JroquTyIt ztFk=i2uiSF{9I(&e7f#0U-nGLjsv21o-ps89dROz>yX2gRqJ+kaPGYL`L;*h*Tc~% zz3Y~z$22IMpS*9fs`1xFB3TcUpWKJ1{dw8gbKC~#FA@;`T4ghg6#_L>(bzF34>wOx86Z*uLNyOO-dW1nCqW=00a#lZ%F z2C{6-p|X4|Vk{z(O;?3H#Li2+oOaP_>zl;vJvYOpz!5L2%pzeR)_`3BKS;kYBjbM- zRs&{6#{bB{&J7NBMuz-E)`v69Vw0mQCq6&-%8B=WGLsDdD(`CX;OYB?qW%hoc*xh? z(mA$IlTAvxE4lqk$L>|)&mIa3{N1?9x$vUjP3?sb=DwJ_hh<;V`c40;v}+QxrYU^P z;a~VGB~0u2WX9yBtjEr6Gqij0faT|;(^WZ6JMyjeUz6W5uV(hQRr{1Cu3k{%zrCu= z!e)Qd)hiR29%o!-To854W4F7F@0{7DbIbQ!^g|KNvwt_rI(4^} c-TJR*JyDG1(-z0shds|mY4aE=_Z+wk03*6t4gdfE literal 0 HcmV?d00001 diff --git a/examples/protocols/mqtt/publish_connect_test/ca.key b/examples/protocols/mqtt/publish_connect_test/ca.key new file mode 100644 index 0000000000..d39ad7c88b --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAyadSpRnIQBVbEAsbpkrKrOMlBOMIUmA8AfNyOYPLfv0Oa5lB +iMAV3OQDu5tYyFYKwkCUqq65iAm50fPbSH71w1tkja6nZ1yAIM+TvpMlM/WiFGrh +Y+TckAcLcKUJyPxrv/glzoVslbqUgIhuhCSKA8uk1+ILcn3nWzPcbcowLx31+AHe +Zj8hbIAdj6vjqxMCFStp4IcA+ikmCk75LCN4vkkifdkebb/ZDNYCZZhpCBnCHyFA +jPc47C+FDVGT3/UUeeTy+Mtn+MqUAhB+W0sPDm1n2h59D4Z/MFm0hl6GQCAKeMJP +zssUBBsRm6zoyPQ4VTqG0uwfNNbORyIfKONMUwIDAQABAoIBAQDEKH7NWcohBGUj +sxp/ZcvH5+FP4qVqtHBLGYyohBsE+Zb4dgl4xBnAWRGEgrYXkxM+KOI1MmgJ/CQF +JujNmarqEVI8PIRdmG6O/D1lKfALnkq+/8Umji87745iUji1iU4rXHEydznMYMYq +TgzrgDu9O3CsDBhElFLktgsbxY2flhRiQ9s/MJTXlfkHYVMbzB+WzbgwglZmzRRB +V9P7GDc1RPs3iUuab2BC0ajWSVWPCIE+WRQ8OTxeSz/Trp0S1y1WtxdMUDhg6wIe +xbTCYF6L6CRjdnnAiaFZuW+ECaeLOyy8sOTtzxIU/8in++x3+CJBaMLsvAG1e2K9 +7OLzz4KZAoGBAObHebhxfC9ue3hGC5IbE7BOaXBBdyHboXvajJKtyqpIDq7QLk2j +ktTuatigrzyCA8GgJUZCuOeWe/JhuzpFAsXN/lVs7ugw/6vQ+RGtJZkxzsYQDQjw +/3f4uWevsj3b28idxdMgstsw12a92pmH3TtKu7mMX2jJhYSu3wqbnCj/AoGBAN+w +/6nH4jLhSobunV+JT3YxwsMdyffLcdwXTcwjJrwGLwNvhPfAGtCCXidneYELCwCF +TbemR5VZadZrCdURWqwyHw8YMHBfN1hArD3MKqck+XK5Spxxr3pfNHvU3YIKWI1l +2h5sKoaPNUTQerLsJh9XG/zyc2Nl88hlFZucTGitAoGAPnKf518eIZ+d3Y/mtaSK +EV1Gfs/YMttBuUgMXeyVOLrC7l77CJtIskHJu9DPWmo8Jfr12ytW6aP46j+z8DKY +a3owZmFRzJbluFKV80iNMgUeVM4nGNJN7uLpGLucWczSjljTHSxt+Y4f23doXb88 +CD1SywTHFI3jiWHgjPhKq3UCgYATBZUoFeRJWVkiEkZ1qlKEhYS/XNgg5z7+bUjj +VBXmJUx4KVKQUti05HEnPqhZbdv4pl1OgahSrfDPF/kVEk24mOaFPRRZae9l5NIA +y0zRO9auh80tcoluiYwH/7j6ZvDSzVd4ANC48pKgEG5uqqAvSBQMNX3UdQX/A4GL +4wWoXQKBgBqtbOYpsoAbLTNV4e7AMZCCKlPYFvRDALbO2E/8MjdaIqBWQSiZBkQ6 +ALFYQaKJOwiLVXVv5B1FHz8MblqDOIaUpaujoA4NxdhYFLh2ui3fzuGTdGiPzOry +QHcIGifGSef45KnrF1LGvGvLMzX7Jx3xnAFOblJikN10wt1MLdNG +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/mqtt/publish_connect_test/client_inv.crt b/examples/protocols/mqtt/publish_connect_test/client_inv.crt new file mode 100644 index 0000000000..e5042f3520 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/client_inv.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgECFBhepE4kbe+jKn9Qa4Fq7o73PL/AMA0GCSqGSIb3DQEBCwUAMIGD +MQswCQYDVQQGEwJDWjEOMAwGA1UECAwFQ3plY2gxDTALBgNVBAcMBEJybm8xEjAQ +BgNVBAoMCUVzcHJlc3NpZjELMAkGA1UECwwCU1cxFDASBgNVBAMMCzE5Mi4xNjgu +Mi4xMR4wHAYJKoZIhvcNAQkBFg9kYXZpZEBjZXJtYWsuY3owHhcNMjAwMTIyMTAy +MDM5WhcNMjkxMTMwMTAyMDM5WjAOMQwwCgYDVQQDDANlc3AwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCtphtVYl80g2ldpmNY0NKcmabqWKGRC5PmabDU +wrqErvyOko68fpfw24bO2ndUyXdIgWtf4mbAFmIKajrNrACzMlDtfcZM2uYgJZdn +CYu/NNfDaFEb/ZyHIgkmVskLNxtv8QFTfaNCKK5Fhzz0iaFJnFAuQVX3kXIgOEN2 +8EmNxP53Eb9FeauVX+PBHhwJcGBruvWLPz8bfybHl51b80lCfddbow3z1zqGLESh +AzGc1j/5AEgEgL+iP3QX4qoLKYBgs/olv3rYor8I7oCYfsIpFCcvr/LEoaVYtCJP +PxbGu6KPx3p+r3MjaDStevdhLmzrKr35KczzTpUdOU3wgJA/AgMBAAEwDQYJKoZI +hvcNAQELBQADggEBABVwInNI7NPozIKXsshp6hfM0hchrAozYRT5sZSwusxQJ80t +Xhva0+RnBn3uaYG2YWULu+4QSgzjJ9vdRsFysuNN+7YpihwZrFHwvoRWes5C4ERE +Mzh5xeoZT1VNdz72KHvBytBUwb+h5FZQpfZ9O3yr2wBVHsi4d7/X5LVEmTxLte89 +sxoMGmSbqTKj7/UOfGZjBi2IuiHs1xOZxaZWW7RTgJiz9VGrhSpwb4j6G55HDhYA +4YODy3+epyVXAHVuy4zosQ8CCgdZgN0exB7pEwVQ21zIuyzrcQgQFPGQFbkXH0ow +1mgONA6PZ9YUZftJBmqBZoTVPLLQuE1aKbhBTAA= +-----END CERTIFICATE----- diff --git a/examples/protocols/mqtt/publish_connect_test/client_no_pwd.key b/examples/protocols/mqtt/publish_connect_test/client_no_pwd.key new file mode 100644 index 0000000000..0d9d0163fc --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/client_no_pwd.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAraYbVWJfNINpXaZjWNDSnJmm6lihkQuT5mmw1MK6hK78jpKO +vH6X8NuGztp3VMl3SIFrX+JmwBZiCmo6zawAszJQ7X3GTNrmICWXZwmLvzTXw2hR +G/2chyIJJlbJCzcbb/EBU32jQiiuRYc89ImhSZxQLkFV95FyIDhDdvBJjcT+dxG/ +RXmrlV/jwR4cCXBga7r1iz8/G38mx5edW/NJQn3XW6MN89c6hixEoQMxnNY/+QBI +BIC/oj90F+KqCymAYLP6Jb962KK/CO6AmH7CKRQnL6/yxKGlWLQiTz8Wxruij8d6 +fq9zI2g0rXr3YS5s6yq9+SnM806VHTlN8ICQPwIDAQABAoIBAA4G8wJMtgAZ9XL5 +M+FCzSCVUORxUGvVEZd1RjGJoWOCdyhVMm6Lk16DfTpMb4NL2vTib3gJY990b2sD +9cgTcuMG1363wEMJE7nZD4flP4KslBlW3eZy8CgCWdbc/9SGGRNL1p2V8pAvlRRM +vmHKlFrL47Y41ObwutVbdievdWGcPBdF/sjpzskemVrEIPg7knHJ+MyxuIsjyaLV +Xdf3RR8yqtRggl+EP6m7JP4mbdlb/key8JTOHhe135JbuIwjUKTvm7UI+r9HwrDF +/4ysd6uEqAq4vD73VJ+7UR1LSWJ1hqoVyNP96QWPsReID/PB8TxbCPNOMX8WKz7U +WXOVomECgYEA1+54rF8QT/cpuqxR3ChbPaRGfwform0/nXZY7Xna4SqifQ2/gd6S +I97cktKCQzsnxqxrq8lV8kBlVBnqYWib+546WNjez32DUTsSu/0cIat649izbhw/ +a9piOttup3OSAmc6LZGgPtLB/Jhupl9F25SbwAxnYyUUSomqK4zSOvkCgYEAzd8O +MNZUGHREjD43UuoM+qyMa1vanZk+0mcNt6cL4MTKVHNyEPdCOg01QcAGTH5pumbs +mxU4yEPGn6RylQuXDi1UwFBsPLQTDRCnbjWkYBSNY3qKD0MlN+UIQ6/zUMaYHVL8 +xEfvJKxMiMdU4FhgDqoCTsK7BjnJ/bzgEdrHevcCgYAS7pOh+UvC1xbPiSA8P0WQ +qACOTrE16do0AhZV6+Mm7sgEUtpBlrQVdQq9zLsjDeK05pUiIKrqbH712rfUBon2 +i67t70XJx2VmD9napZx7zz8dDvjcZJmi6SjHpEmVYOqiT06ohCYam/vqG6tH5v6G +/AaT1gKSjMO0rVFAND6ScQKBgF459ZjMwHjg3m8CGvhMP9yMFUkeJZV0iphqqpCg +WINsDt9QZ6j0Qs+nM/UAGuHwChxS94CT2gVvX/25mug1AdJvVRcguCmgkges07VR +wAZp4bziXUZXCTXoEjxI0CjsfLsPPLnp4r76TZ1c/rAgQvbzQVMjNc7HrHgCdtw1 +MpBJAoGAEdeW0t5kHrHHYlFqwUHYnwD6DbNl4TzTumZrI+uEkrH1EAQ4BpIk5Gwx +OOWw8m+x2AMtBk+XcElMGZbX98msB2KcHbQMuxLF3xbCB5ihm6sKxk0HLvf2kygP +k+DYz710yKq9zRwoGOeM52oTrA4hIpQKBnpjCXg9QigD0yoWOjI= +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/mqtt/publish_connect_test/client_pwd.crt b/examples/protocols/mqtt/publish_connect_test/client_pwd.crt new file mode 100644 index 0000000000..50c291a10e --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/client_pwd.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7jCCAdYCFDLr5uidhcbJKmiKv+FoJ2lyh2ZkMA0GCSqGSIb3DQEBCwUAMFkx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yMDAx +MjIxMDA1MThaFw0yOTExMzAxMDA1MThaMA4xDDAKBgNVBAMMA2VzcDCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2mG1ViXzSDaV2mY1jQ0pyZpupYoZEL +k+ZpsNTCuoSu/I6Sjrx+l/Dbhs7ad1TJd0iBa1/iZsAWYgpqOs2sALMyUO19xkza +5iAll2cJi78018NoURv9nIciCSZWyQs3G2/xAVN9o0IorkWHPPSJoUmcUC5BVfeR +ciA4Q3bwSY3E/ncRv0V5q5Vf48EeHAlwYGu69Ys/Pxt/JseXnVvzSUJ911ujDfPX +OoYsRKEDMZzWP/kASASAv6I/dBfiqgspgGCz+iW/etiivwjugJh+wikUJy+v8sSh +pVi0Ik8/Fsa7oo/Hen6vcyNoNK1692EubOsqvfkpzPNOlR05TfCAkD8CAwEAATAN +BgkqhkiG9w0BAQsFAAOCAQEAxRyJBo1GP5K5BFvJDeXcAJjUbzFUqY4pUsbodkIZ +NJj69ZulxARISKsqaVhjR0m4CXZMRVhimRUJJBnjgTYidWF/xsbxgmEoURqV9SAL +puYMOm3t9Fi/81iQSzvT6ZLq5bQmxCFpZ6jl+nM28KqqldhRJApgXLOvc9i/N1FW +7ceZPw33vfzKxk91rVl9vv+wBLS/jeF++6wscIeFW+HjDj2F84JEENltoEpQz4Y1 +VWYJ2G5Fu0MaxObwMrEqIxKAq7X96pyIocO6vINg0UWNp3kbPBSzD1i5FLqx96fQ +kfykJJN1kUsrJk1PskxnWq2vckdSv+jLOiF7hoHRG7+69A== +-----END CERTIFICATE----- diff --git a/examples/protocols/mqtt/publish_connect_test/client_pwd.key b/examples/protocols/mqtt/publish_connect_test/client_pwd.key new file mode 100644 index 0000000000..ce98682401 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/client_pwd.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,6FFF58C7A652F8E0D7E31F0CCAA27E98 + +ZUeJ8iCLa7bDf8xQsL3NtDK/oR2z8EWapoqGru/zOvxAeHWoLdMko1bouMkEXn+h +g4GigyXo9f3jdyFKeqf9TtXonL6vguWczFc+81ynE5w3iqqcmdP8SD8k3o07lBc/ +hfRIwsg4Ywda3luQBWT63LIx7GnQjHRjK/KkPkFkYG6LDwshWyf1L7NxRMCrkejA +3B7KqlRTEia9xR0WH//ZGOdipp2MSyUGC46BgXJQ1rDJo1D+3NUTZ8RmMkqZNmJK +z3HMMflB4khmh2HkdM10VaErpiphitP52aTbGu/aschDOvSHFYMNf916u8UlyGQJ +4m/pgSz+aAfReGRDqCcojkAf/BR4+n7QYfFtxjJ5P4ul4ZnhB30synknet6+9bKU +Ht1SkavyJmruW2sfIcvPadLVm+xROnGr3ZWs82BGdPPu4wIYRWBn4S7huELXSSC2 +qLCTWeLB+pV//+9E9EmrvwsTJBNMCkjAmmTdmofm8UisAGsZlvyIDJVlpUsUKOoU +cHGc2x9hj5OhgK++0JOY2ftowFX69FNRYNYHB5Vw6/5Teo3eGxVYoMeosADo7pXa +j17g7dywDLRBZuTfIkFcYyfRV4A/xcagZJ8m/rnSDphGHYkM1d+MoXAPhj6A+iAa +2qZkPyYdd0OkWvCY42F2xsjxzYjmxvkkNLDiYa7zj3ofb/1mqdNc8/k2AbFObX4v +LenDFyqmzeYfzHcJ2Z4edwx1TFFMlHb+knuYjSzcBceWoQ5nOi+uipgZVJEEKC8o +vTUBeaDnRblNIGlvuWnZFN0OHV1BduF5TyKUh2YGBw/X4qgCgrnCR2I8HGZMkUNe +UTDF9vpxnDke5BEhzkwb2R34Kvn7ac1p4NDdXOrCwEqZTt93FgQTgOuklPb39CcZ +yQHfl1Vr0EgfOlcE+ngbUrU93/qsEADXyjM8D4ZGB5+tQZGWlz9nc8PqldC3txux +Hce4bk98hOgZUy/fEozE6fODxBJCuIi2ab/6WU8j62UAIumw7fvgti+zor6eJdas +QCS+UVj5fJtYc5E/7Urih7Ixkltu0atqR5p81xn8U94/6KGYUCcsaZ7UZnWfD4dF +0qEkdHravD82Z38eBpt/kqIE7bHs3orvt7WSCBYZQtkdQysYy+lXEAwF3eIpCqAW +EcdHZ10zENvSHfzot1yK2rk9uuD+KqyK80xCSh9auLBSdJHCNeMtaozpCg5jLhYu +mW4zSQA4awuD58k/+xAnOzXtNCPg6TPQ7GNzX/33W9R2ceRtkbNmd68YEmkZ7tZo +s/3DAuxjid5W+wbsJHBvnUQh9g5BMF18k0SYS3bFPy62eycQziGfEQIwcgaHqAt5 +SX4URYqDLN0k+68CAQfm2JAS8kOBdo9TAKsluThp/uRC1oh3DW/D0xctDAApDbdd +oNnK44XSYfMsBaGjm+NFQYTndFDpSd4+eQcVWAaXTdyRGMC6jbc9XijdzJnnKbEP +M38+5dUaZFPyONieb7VfciH1WKM0GfxHAFxpiEgXd0dwS8Jqq9sLY6drKZP5+b9a +9KMXI3jBLVqPg9yvx8E7THjF9ihsheVhEcJ6Nywhopab9Et+wvFa9upl2TJ2xGIj +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/mqtt/publish_connect_test/example_test.py b/examples/protocols/mqtt/publish_connect_test/example_test.py new file mode 100644 index 0000000000..ccc3e06ee6 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/example_test.py @@ -0,0 +1,230 @@ +from __future__ import print_function +from __future__ import unicode_literals +import re +import os +import socket +import select +import subprocess +from threading import Thread, Event +import ttfw_idf +import ssl + + +def _path(f): + return os.path.join(os.path.dirname(os.path.realpath(__file__)),f) + + +def set_server_cert_cn(ip): + arg_list = [ + ['openssl', 'req', '-out', _path('srv.csr'), '-key', _path('server.key'),'-subj', "/CN={}".format(ip), '-new'], + ['openssl', 'x509', '-req', '-in', _path('srv.csr'), '-CA', _path('ca.crt'), + '-CAkey', _path('ca.key'), '-CAcreateserial', '-out', _path('srv.crt'), '-days', '360']] + for args in arg_list: + if subprocess.check_call(args) != 0: + raise("openssl command {} failed".format(args)) + + +def get_my_ip(): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + # doesn't even have to be reachable + s.connect(('10.255.255.255', 1)) + IP = s.getsockname()[0] + except Exception: + IP = '127.0.0.1' + finally: + s.close() + return IP + + +# Simple server for mqtt over TLS connection +class TlsServer: + + def __init__(self, port, client_cert=False, refuse_connection=False, use_alpn=False): + self.port = port + self.socket = socket.socket() + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.settimeout(10.0) + self.shutdown = Event() + self.client_cert = client_cert + self.refuse_connection = refuse_connection + self.ssl_error = None + self.use_alpn = use_alpn + self.negotiated_protocol = None + + def __enter__(self): + try: + self.socket.bind(('', self.port)) + except socket.error as e: + print("Bind failed:{}".format(e)) + raise + + self.socket.listen(1) + self.server_thread = Thread(target=self.run_server) + self.server_thread.start() + + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.shutdown.set() + self.server_thread.join() + self.socket.close() + if (self.conn is not None): + self.conn.close() + + def get_last_ssl_error(self): + return self.ssl_error + + def get_negotiated_protocol(self): + return self.negotiated_protocol + + def run_server(self): + context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + if self.client_cert: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=_path("ca.crt")) + context.load_cert_chain(certfile=_path("srv.crt"), keyfile=_path("server.key")) + if self.use_alpn: + context.set_alpn_protocols(["mymqtt", "http/1.1"]) + self.socket = context.wrap_socket(self.socket, server_side=True) + try: + self.conn, address = self.socket.accept() # accept new connection + self.socket.settimeout(10.0) + print(" - connection from: {}".format(address)) + if self.use_alpn: + self.negotiated_protocol = self.conn.selected_alpn_protocol() + print(" - negotiated_protocol: {}".format(self.negotiated_protocol)) + self.handle_conn() + except ssl.SSLError as e: + self.conn = None + self.ssl_error = str(e) + print(" - SSLError: {}".format(str(e))) + + def handle_conn(self): + while not self.shutdown.is_set(): + r,w,e = select.select([self.conn], [], [], 1) + try: + if self.conn in r: + self.process_mqtt_connect() + + except socket.error as err: + print(" - error: {}".format(err)) + raise + + def process_mqtt_connect(self): + try: + data = bytearray(self.conn.recv(1024)) + message = ''.join(format(x, '02x') for x in data) + if message[0:16] == '101800044d515454': + if self.refuse_connection is False: + print(" - received mqtt connect, sending ACK") + self.conn.send(bytearray.fromhex("20020000")) + else: + # injecting connection not authorized error + print(" - received mqtt connect, sending NAK") + self.conn.send(bytearray.fromhex("20020005")) + else: + raise Exception(" - error process_mqtt_connect unexpected connect received: {}".format(message)) + finally: + # stop the server after the connect message in happy flow, or if any exception occur + self.shutdown.set() + + +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_mqtt_publish_connect(env, extra_data): + """ + steps: + 1. join AP + 2. connect to uri specified in the config + 3. send and receive data + """ + dut1 = env.get_dut("mqtt_publish_connect_test", "examples/protocols/mqtt/publish_connect_test", dut_class=ttfw_idf.ESP32DUT) + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "mqtt_publish_connect_test.bin") + bin_size = os.path.getsize(binary_file) + ttfw_idf.log_performance("mqtt_publish_connect_test_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("mqtt_publish_connect_test_bin_size_vin_size", bin_size // 1024) + # Look for test case symbolic names + cases = {} + try: + for i in ["CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT", + "CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT", + "CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH", + "CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT", + "CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT", + "CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD", + "CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT", + "CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN"]: + cases[i] = dut1.app.get_sdkconfig()[i] + except Exception: + print('ENV_TEST_FAILURE: Some mandatory test case not found in sdkconfig') + raise + + dut1.start_app() + esp_ip = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) + print("Got IP={}".format(esp_ip[0])) + # + # start connection test + ip = get_my_ip() + set_server_cert_cn(ip) + server_port = 2222 + + def start_case(case, desc): + print("Starting {}: {}".format(case, desc)) + case_id = cases[case] + dut1.write("conn {} {} {}".format(ip, server_port, case_id)) + dut1.expect("Test case:{} started".format(case_id)) + return case_id + + for case in ["CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT", "CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT", "CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT"]: + # All these cases connect to the server with no server verification or with server only verification + with TlsServer(server_port): + test_nr = start_case(case, "default server - expect to connect normally") + dut1.expect("MQTT_EVENT_CONNECTED: Test={}".format(test_nr), timeout=30) + with TlsServer(server_port, refuse_connection=True): + test_nr = start_case(case, "ssl shall connect, but mqtt sends connect refusal") + dut1.expect("MQTT_EVENT_ERROR: Test={}".format(test_nr), timeout=30) + dut1.expect("MQTT ERROR: 0x5") # expecting 0x5 ... connection not authorized error + with TlsServer(server_port, client_cert=True) as s: + test_nr = start_case(case, "server with client verification - handshake error since client presents no client certificate") + dut1.expect("MQTT_EVENT_ERROR: Test={}".format(test_nr), timeout=30) + dut1.expect("ESP-TLS ERROR: 0x8010") # expect ... handshake error (PEER_DID_NOT_RETURN_A_CERTIFICATE) + if "PEER_DID_NOT_RETURN_A_CERTIFICATE" not in s.get_last_ssl_error(): + raise("Unexpected ssl error from the server {}".format(s.get_last_ssl_error())) + + for case in ["CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH", "CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD"]: + # These cases connect to server with both server and client verification (client key might be password protected) + with TlsServer(server_port, client_cert=True): + test_nr = start_case(case, "server with client verification - expect to connect normally") + dut1.expect("MQTT_EVENT_CONNECTED: Test={}".format(test_nr), timeout=30) + + case = "CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT" + with TlsServer(server_port) as s: + test_nr = start_case(case, "invalid server certificate on default server - expect ssl handshake error") + dut1.expect("MQTT_EVENT_ERROR: Test={}".format(test_nr), timeout=30) + dut1.expect("ESP-TLS ERROR: 0x8010") # expect ... handshake error (TLSV1_ALERT_UNKNOWN_CA) + if "alert unknown ca" not in s.get_last_ssl_error(): + raise Exception("Unexpected ssl error from the server {}".format(s.get_last_ssl_error())) + + case = "CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT" + with TlsServer(server_port, client_cert=True) as s: + test_nr = start_case(case, "Invalid client certificate on server with client verification - expect ssl handshake error") + dut1.expect("MQTT_EVENT_ERROR: Test={}".format(test_nr), timeout=30) + dut1.expect("ESP-TLS ERROR: 0x8010") # expect ... handshake error (CERTIFICATE_VERIFY_FAILED) + if "CERTIFICATE_VERIFY_FAILED" not in s.get_last_ssl_error(): + raise Exception("Unexpected ssl error from the server {}".format(s.get_last_ssl_error())) + + for case in ["CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT", "CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN"]: + with TlsServer(server_port, use_alpn=True) as s: + test_nr = start_case(case, "server with alpn - expect connect, check resolved protocol") + dut1.expect("MQTT_EVENT_CONNECTED: Test={}".format(test_nr), timeout=30) + if case == "CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT" and s.get_negotiated_protocol() is None: + print(" - client with alpn off, no negotiated protocol: OK") + elif case == "CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN" and s.get_negotiated_protocol() == "mymqtt": + print(" - client with alpn on, negotiated protocol resolved: OK") + else: + raise Exception("Unexpected negotiated protocol {}".format(s.get_negotiated_protocol())) + + +if __name__ == '__main__': + test_examples_protocol_mqtt_publish_connect() diff --git a/examples/protocols/mqtt/publish_connect_test/main/CMakeLists.txt b/examples/protocols/mqtt/publish_connect_test/main/CMakeLists.txt new file mode 100644 index 0000000000..85e306a56f --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "publish_test.c" "connect_test.c" "publish_connect_test.c" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/protocols/mqtt/publish_test/main/Kconfig.projbuild b/examples/protocols/mqtt/publish_connect_test/main/Kconfig.projbuild similarity index 63% rename from examples/protocols/mqtt/publish_test/main/Kconfig.projbuild rename to examples/protocols/mqtt/publish_connect_test/main/Kconfig.projbuild index bf4197482e..874db25c4b 100644 --- a/examples/protocols/mqtt/publish_test/main/Kconfig.projbuild +++ b/examples/protocols/mqtt/publish_connect_test/main/Kconfig.projbuild @@ -47,4 +47,39 @@ menu "Example Configuration" bool default y if EXAMPLE_BROKER_CERTIFICATE_OVERRIDE != "" + config EXAMPLE_CONNECT_CASE_NO_CERT + # Note: All the below config values (EXAMPLE_CONNECT_CASE...) are hidden and + # used to give symbolic names to test cases, which are then referenced from both + # the embedded C code as well as the test counterpart in python + int + default 1 + + config EXAMPLE_CONNECT_CASE_SERVER_CERT + int + default 2 + + config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH + int + default 3 + + config EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT + int + default 4 + + config EXAMPLE_CONNECT_CASE_SERVER_DER_CERT + int + default 5 + + config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD + int + default 6 + + config EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT + int + default 7 + + config EXAMPLE_CONNECT_CASE_NO_CERT_ALPN + int + default 8 + endmenu diff --git a/examples/protocols/mqtt/publish_connect_test/main/component.mk b/examples/protocols/mqtt/publish_connect_test/main/component.mk new file mode 100644 index 0000000000..ba6d98626f --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/main/component.mk @@ -0,0 +1 @@ +COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem ../ca.crt ../ca.der ../client_pwd.key ../client_pwd.crt ../client_no_pwd.key ../client_inv.crt diff --git a/examples/protocols/mqtt/publish_connect_test/main/connect_test.c b/examples/protocols/mqtt/publish_connect_test/main/connect_test.c new file mode 100644 index 0000000000..7cee6bda5c --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/main/connect_test.c @@ -0,0 +1,237 @@ +/* MQTT connect test + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "esp_netif.h" + +#include "esp_log.h" +#include "mqtt_client.h" +#include "esp_tls.h" + +#if (!defined(CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT)) || \ + (!defined(CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN)) +#error "Some mandatory test case not defined!" +#endif + +extern const uint8_t ca_local_crt[] asm("_binary_ca_crt_start"); +extern const uint8_t ca_der_start[] asm("_binary_ca_der_start"); +extern const uint8_t ca_der_end[] asm("_binary_ca_der_end"); +extern const uint8_t client_pwd_crt[] asm("_binary_client_pwd_crt_start"); +extern const uint8_t client_pwd_key[] asm("_binary_client_pwd_key_start"); +extern const uint8_t client_inv_crt[] asm("_binary_client_inv_crt_start"); +extern const uint8_t client_no_pwd_key[] asm("_binary_client_no_pwd_key_start"); + +static const char *TAG = "CONNECT_TEST"; +static esp_mqtt_client_handle_t mqtt_client = NULL; +static int running_test_case = 0; + +static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +{ + esp_mqtt_event_handle_t event = event_data; + ESP_LOGD(TAG, "Event: %d, Test case: %d", event->event_id, running_test_case); + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED: Test=%d", running_test_case); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR: Test=%d", running_test_case); + if (event->error_handle->error_type == MQTT_ERROR_TYPE_ESP_TLS) { + ESP_LOGI(TAG, "ESP-TLS ERROR: 0x%x", event->error_handle->esp_tls_last_esp_err); + } else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { + ESP_LOGI(TAG, "MQTT ERROR: 0x%x", event->error_handle->connect_return_code); + } else { + ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type); + } + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } +} + +static void create_client(void) +{ + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtts://127.0.0.1:1234" + }; + esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); + esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); + mqtt_client = client; + esp_mqtt_client_start(client); +} + +static void connect_no_certs(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_client_key_password(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)ca_local_crt, + .client_cert_pem = (const char *)client_pwd_crt, + .client_key_pem = (const char *)client_pwd_key, + .clientkey_password = "esp32", + .clientkey_password_len = 5 + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_server_der_cert(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)ca_der_start, + .cert_len = ca_der_end - ca_der_start, + .client_cert_pem = "NULL", + .client_key_pem = "NULL" + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_wrong_server_cert(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)client_pwd_crt, + .client_cert_pem = "NULL", + .client_key_pem = "NULL" + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_server_cert(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)ca_local_crt, + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_server_client_certs(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)ca_local_crt, + .client_cert_pem = (const char *)client_pwd_crt, + .client_key_pem = (const char *)client_no_pwd_key + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_invalid_client_certs(const char *host, const int port) +{ + char uri[64]; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .cert_pem = (const char *)ca_local_crt, + .client_cert_pem = (const char *)client_inv_crt, + .client_key_pem = (const char *)client_no_pwd_key + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +static void connect_with_alpn(const char *host, const int port) +{ + char uri[64]; + const char *alpn_protos[] = { "mymqtt", NULL }; + sprintf(uri, "mqtts://%s:%d", host, port); + const esp_mqtt_client_config_t mqtt_cfg = { + .uri = uri, + .alpn_protos = alpn_protos + }; + esp_mqtt_set_config(mqtt_client, &mqtt_cfg); + esp_mqtt_client_disconnect(mqtt_client); + esp_mqtt_client_reconnect(mqtt_client); +} + +void connection_test(const char* line) +{ + char test_type[32]; + char host[32]; + int port; + int test_case; + + sscanf(line, "%s %s %d %d", test_type, host, &port, &test_case); + if (mqtt_client == NULL) { + create_client(); + } + ESP_LOGI(TAG, "CASE:%d, connecting to mqtts://%s:%d ", test_case, host, port); + running_test_case = test_case; + switch (test_case) { + case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT: + connect_no_certs(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_CERT: + connect_with_server_cert(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH: + connect_with_server_client_certs(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_INVALID_SERVER_CERT: + connect_with_wrong_server_cert(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_SERVER_DER_CERT: + connect_with_server_der_cert(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_KEY_PWD: + connect_with_client_key_password(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_MUTUAL_AUTH_BAD_CRT: + connect_with_invalid_client_certs(host, port); + break; + case CONFIG_EXAMPLE_CONNECT_CASE_NO_CERT_ALPN: + connect_with_alpn(host, port); + break; + default: + ESP_LOGE(TAG, "Unknown test case %d ", test_case); + break; + } + ESP_LOGI(TAG, "Test case:%d started", test_case); +} + + diff --git a/examples/protocols/mqtt/publish_test/main/mqtt_eclipse_org.pem b/examples/protocols/mqtt/publish_connect_test/main/mqtt_eclipse_org.pem similarity index 100% rename from examples/protocols/mqtt/publish_test/main/mqtt_eclipse_org.pem rename to examples/protocols/mqtt/publish_connect_test/main/mqtt_eclipse_org.pem diff --git a/examples/protocols/mqtt/publish_connect_test/main/publish_connect_test.c b/examples/protocols/mqtt/publish_connect_test/main/publish_connect_test.c new file mode 100644 index 0000000000..fa7336c498 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/main/publish_connect_test.c @@ -0,0 +1,76 @@ +/* MQTT publish-connect test + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include "esp_system.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "protocol_examples_common.h" +#include "esp_log.h" + +static const char *TAG = "PUBLISH_CONNECT_TEST"; + +void connection_test(const char* line); +void publish_test(const char* line); + +static void get_string(char *line, size_t size) +{ + int count = 0; + while (count < size) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} + +void app_main(void) +{ + char line[256]; + + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + esp_log_level_set("*", ESP_LOG_INFO); + esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); + esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); + esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + while (1) { + get_string(line, sizeof(line)); + if (memcmp(line, "conn", 4) == 0) { + // line starting with "conn" indicate connection tests + connection_test(line); + get_string(line, sizeof(line)); + continue; + } else { + publish_test(line); + } + } + +} \ No newline at end of file diff --git a/examples/protocols/mqtt/publish_connect_test/main/publish_test.c b/examples/protocols/mqtt/publish_connect_test/main/publish_test.c new file mode 100644 index 0000000000..c78a84e0d5 --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/main/publish_test.c @@ -0,0 +1,175 @@ +/* MQTT publish test + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_log.h" +#include "mqtt_client.h" + +static const char *TAG = "PUBLISH_TEST"; + +static EventGroupHandle_t mqtt_event_group; +const static int CONNECTED_BIT = BIT0; + +static esp_mqtt_client_handle_t mqtt_client = NULL; + +static char *expected_data = NULL; +static char *actual_data = NULL; +static size_t expected_size = 0; +static size_t expected_published = 0; +static size_t actual_published = 0; +static int qos_test = 0; + + #if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1 + static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; + #else + extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); + #endif + extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); + +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +{ + esp_mqtt_client_handle_t client = event->client; + static int msg_id = 0; + static int actual_len = 0; + // your_context_t *context = event->context; + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT); + msg_id = esp_mqtt_client_subscribe(client, CONFIG_EXAMPLE_SUBSCIBE_TOPIC, qos_test); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + printf("DATA=%.*s\r\n", event->data_len, event->data); + printf("ID=%d, total_len=%d, data_len=%d, current_data_offset=%d\n", event->msg_id, event->total_data_len, event->data_len, event->current_data_offset); + if (event->topic) { + actual_len = event->data_len; + msg_id = event->msg_id; + } else { + actual_len += event->data_len; + // check consisency with msg_id across multiple data events for single msg + if (msg_id != event->msg_id) { + ESP_LOGI(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id); + abort(); + } + } + memcpy(actual_data + event->current_data_offset, event->data, event->data_len); + if (actual_len == event->total_data_len) { + if (0 == memcmp(actual_data, expected_data, expected_size)) { + printf("OK!"); + memset(actual_data, 0, expected_size); + actual_published ++; + if (actual_published == expected_published) { + printf("Correct pattern received exactly x times\n"); + ESP_LOGI(TAG, "Test finished correctly!"); + } + } else { + printf("FAILED!"); + abort(); + } + } + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } + return ESP_OK; +} + + +static void mqtt_app_start(void) +{ + mqtt_event_group = xEventGroupCreate(); + const esp_mqtt_client_config_t mqtt_cfg = { + .event_handle = mqtt_event_handler, + .cert_pem = (const char *)mqtt_eclipse_org_pem_start, + }; + + ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + mqtt_client = esp_mqtt_client_init(&mqtt_cfg); +} + +void publish_test(const char* line) +{ + char pattern[32]; + char transport[32]; + int repeat = 0; + static bool is_mqtt_init = false; + + if (!is_mqtt_init) { + mqtt_app_start(); + is_mqtt_init = true; + } + sscanf(line, "%s %s %d %d %d", transport, pattern, &repeat, &expected_published, &qos_test); + ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d\n", pattern, repeat, expected_published); + int pattern_size = strlen(pattern); + free(expected_data); + free(actual_data); + actual_published = 0; + expected_size = pattern_size * repeat; + expected_data = malloc(expected_size); + actual_data = malloc(expected_size); + for (int i = 0; i < repeat; i++) { + memcpy(expected_data + i * pattern_size, pattern, pattern_size); + } + printf("EXPECTED STRING %.*s, SIZE:%d\n", expected_size, expected_data, expected_size); + esp_mqtt_client_stop(mqtt_client); + + if (0 == strcmp(transport, "tcp")) { + ESP_LOGI(TAG, "[TCP transport] Startup.."); + esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_TCP_URI); + } else if (0 == strcmp(transport, "ssl")) { + ESP_LOGI(TAG, "[SSL transport] Startup.."); + esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_SSL_URI); + } else if (0 == strcmp(transport, "ws")) { + ESP_LOGI(TAG, "[WS transport] Startup.."); + esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WS_URI); + } else if (0 == strcmp(transport, "wss")) { + ESP_LOGI(TAG, "[WSS transport] Startup.."); + esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WSS_URI); + } else { + ESP_LOGE(TAG, "Unexpected transport"); + abort(); + } + xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT); + esp_mqtt_client_start(mqtt_client); + ESP_LOGI(TAG, "Note free memory: %d bytes", esp_get_free_heap_size()); + xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); + + for (int i = 0; i < expected_published; i++) { + int msg_id = esp_mqtt_client_publish(mqtt_client, CONFIG_EXAMPLE_PUBLISH_TOPIC, expected_data, expected_size, qos_test, 0); + ESP_LOGI(TAG, "[%d] Publishing...", msg_id); + } +} diff --git a/examples/protocols/mqtt/publish_test/sdkconfig.ci b/examples/protocols/mqtt/publish_connect_test/sdkconfig.ci similarity index 100% rename from examples/protocols/mqtt/publish_test/sdkconfig.ci rename to examples/protocols/mqtt/publish_connect_test/sdkconfig.ci diff --git a/examples/protocols/mqtt/publish_test/sdkconfig.qemu b/examples/protocols/mqtt/publish_connect_test/sdkconfig.qemu similarity index 100% rename from examples/protocols/mqtt/publish_test/sdkconfig.qemu rename to examples/protocols/mqtt/publish_connect_test/sdkconfig.qemu diff --git a/examples/protocols/mqtt/publish_connect_test/server.key b/examples/protocols/mqtt/publish_connect_test/server.key new file mode 100644 index 0000000000..2a4d650eac --- /dev/null +++ b/examples/protocols/mqtt/publish_connect_test/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAlUCywNhVv4RO2y9h/XGKZ1azzk3jzHpSBzIGO9LoiA8trC/p +1ykGaUfYPJllYK4HMhC4fUyE3J7tVL2Eskzl26LNPLbEoaBWZM9NhV3iA1/1EtOu +p6umLx+y3sDfvK35YAOUbjdAlBfhnJ4r8h7oTsxl3J5jZ18zgjJnJi2NEFq/yTpO +MiwHLWPjy25fDFixfV9UzSvbgt1JaGPmC7c4QkhHzjyp0+ikuvRIw0p9BBNeqBV2 +da3qBMB5FtodUJTAz6o6OKWbTalLjQi6C1H6z9TnY7IrJBUOy/FWkQH/sEsLdscD +hHa1Dz2oT203QjhzyOSfnNF95D/1MdNcMt6l0wIDAQABAoIBAC1JJTOoMFRc48RT +myrYQYNbZlEphv3q+2qdfhC2zMFDwbrmCtCy7PQSzYSNkpoEE8DYG/JAvmtmeWJl +4pZrCK9ctWM/nWfhC3WpBL97nfEiM20T94F+bn0L5Cz8XqaULv839th+QUTt/hGU +WIctY5VNJXcMQ+MAmtNdUbjex1d3iuxiKHUo4nDoZ8digKFNdtdP5B5nlMq5chCL +mxNRcsGsx2dDAxbGUapdTVPWHPJKpLOBoSkluDsfd2KZADFU2R1SJpAX9+RYh3HM +5FTUdHTUaISxbKkgeDKlEM0lqk2TtGUwCyEj098ewi7Wzsu9w60IplPPUJx5FRG6 +jp3wzLkCgYEAxKp5T20rf/7ysX7x053I7VCjDXUxAaWOEj1uS3AhOkl0NaZg7Di+ +y53fWNkcHdkt2n2LqMt/43UgMYq3TVVcq2eunPNF11e1bJw8CjDafwDs4omwwyVn +lYhPuB4dK2OAib+vU5Zqpp0kZMoxk2MZVgon8z+s8DW/zmB6aFqAWeUCgYEAwkhC +OgmXKMdjOCVy5t2f5UbY8Y9rV3w8eUATuJ47MMwLr4pGYnKoEn9JB4ltWrHv/u5S +fOv3tIrrCEvnCoCbOILwCsY5LqTNXgqova8FB6RpMUQCzhDd8LHuvdHv0WMnMzX1 +3PKuqwh8JS55m4WqZRhzr5BFKG4fHPVs4IcaJVcCgYAzzCaJSdqUKqTnJOUydDNQ +ddWMHNqccWs62J0tF0pZHLGT089hSAzQejMyJnSmU+Ykzr4y5e44DUg+ZCelIZ93 +saYmxlgVwI8THQ8fLADQRIEfpV4996MRmkZM2vmZzOo03Zyi6lIKsga82Rg3lnk8 +1Q3ynknBNpbfF0AGLhfyFQKBgBYlxJ73HutAJ5hr9HhLBYJOnEaVUehMOlycKGNg +bmD2sdJWEgYBChXpurqIORYguLo4EuE4ySkkuPxeIr14wbkkfBbOWBBwKxUwY+IT +xKAFZxR9q1AwbgyVTCEJgKw/AGX/HcMNS0omEnjunmBTUYRq0C1QZgHg490aQUor +PJjLAoGAevzdTpFlVeuKeYh1oDubGO1LinyXpBv7fPFjl+zu4AVbjojcU6yC4OO6 +QvqopE6SyAECKy8kAOFcESPsGc9Lta2XUvI203z7pIVlNVEcJ0+90mQh3Mn1U46l +sZ49PdRvNwNb5wvkh1UqNsMlGFbRlzMbIk45ou4311kCobowZek= +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/mqtt/publish_test/CMakeLists.txt b/examples/protocols/mqtt/publish_test/CMakeLists.txt deleted file mode 100644 index 4a46af3e58..0000000000 --- a/examples/protocols/mqtt/publish_test/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -# (Not part of the boilerplate) -# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) - -project(mqtt_publish) - -target_add_binary_data(mqtt_publish.elf "main/mqtt_eclipse_org.pem" TEXT) diff --git a/examples/protocols/mqtt/publish_test/main/CMakeLists.txt b/examples/protocols/mqtt/publish_test/main/CMakeLists.txt deleted file mode 100644 index 67c4c7b5ad..0000000000 --- a/examples/protocols/mqtt/publish_test/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "publish_test.c" - INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/protocols/mqtt/publish_test/main/component.mk b/examples/protocols/mqtt/publish_test/main/component.mk deleted file mode 100644 index 597752fb9b..0000000000 --- a/examples/protocols/mqtt/publish_test/main/component.mk +++ /dev/null @@ -1 +0,0 @@ -COMPONENT_EMBED_TXTFILES := mqtt_eclipse_org.pem diff --git a/examples/protocols/mqtt/publish_test/main/publish_test.c b/examples/protocols/mqtt/publish_test/main/publish_test.c deleted file mode 100644 index b6b7e53a6d..0000000000 --- a/examples/protocols/mqtt/publish_test/main/publish_test.c +++ /dev/null @@ -1,226 +0,0 @@ -/* MQTT publish test - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include -#include "esp_wifi.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "protocol_examples_common.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/event_groups.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" - -#include "esp_log.h" -#include "mqtt_client.h" - -static const char *TAG = "PUBLISH_TEST"; - -static EventGroupHandle_t mqtt_event_group; -const static int CONNECTED_BIT = BIT0; - -static esp_mqtt_client_handle_t mqtt_client = NULL; - -static char *expected_data = NULL; -static char *actual_data = NULL; -static size_t expected_size = 0; -static size_t expected_published = 0; -static size_t actual_published = 0; -static int qos_test = 0; - - -#if CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDDEN == 1 -static const uint8_t mqtt_eclipse_org_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_EXAMPLE_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----"; -#else -extern const uint8_t mqtt_eclipse_org_pem_start[] asm("_binary_mqtt_eclipse_org_pem_start"); -#endif -extern const uint8_t mqtt_eclipse_org_pem_end[] asm("_binary_mqtt_eclipse_org_pem_end"); - -static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) -{ - esp_mqtt_client_handle_t client = event->client; - static int msg_id = 0; - static int actual_len = 0; - // your_context_t *context = event->context; - switch (event->event_id) { - case MQTT_EVENT_CONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); - xEventGroupSetBits(mqtt_event_group, CONNECTED_BIT); - msg_id = esp_mqtt_client_subscribe(client, CONFIG_EXAMPLE_SUBSCIBE_TOPIC, qos_test); - ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); - - break; - case MQTT_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); - break; - - case MQTT_EVENT_SUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_UNSUBSCRIBED: - ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_PUBLISHED: - ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); - break; - case MQTT_EVENT_DATA: - ESP_LOGI(TAG, "MQTT_EVENT_DATA"); - printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); - printf("DATA=%.*s\r\n", event->data_len, event->data); - printf("ID=%d, total_len=%d, data_len=%d, current_data_offset=%d\n", event->msg_id, event->total_data_len, event->data_len, event->current_data_offset); - if (event->topic) { - actual_len = event->data_len; - msg_id = event->msg_id; - } else { - actual_len += event->data_len; - // check consisency with msg_id across multiple data events for single msg - if (msg_id != event->msg_id) { - ESP_LOGI(TAG, "Wrong msg_id in chunked message %d != %d", msg_id, event->msg_id); - abort(); - } - } - memcpy(actual_data + event->current_data_offset, event->data, event->data_len); - if (actual_len == event->total_data_len) { - if (0 == memcmp(actual_data, expected_data, expected_size)) { - printf("OK!"); - memset(actual_data, 0, expected_size); - actual_published ++; - if (actual_published == expected_published) { - printf("Correct pattern received exactly x times\n"); - ESP_LOGI(TAG, "Test finished correctly!"); - } - } else { - printf("FAILED!"); - abort(); - } - } - break; - case MQTT_EVENT_ERROR: - ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); - break; - default: - ESP_LOGI(TAG, "Other event id:%d", event->event_id); - break; - } - return ESP_OK; -} - - -static void mqtt_app_start(void) -{ - mqtt_event_group = xEventGroupCreate(); - const esp_mqtt_client_config_t mqtt_cfg = { - .event_handle = mqtt_event_handler, - .cert_pem = (const char *)mqtt_eclipse_org_pem_start, - }; - - ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); - mqtt_client = esp_mqtt_client_init(&mqtt_cfg); -} - -static void get_string(char *line, size_t size) -{ - - int count = 0; - while (count < size) { - int c = fgetc(stdin); - if (c == '\n') { - line[count] = '\0'; - break; - } else if (c > 0 && c < 127) { - line[count] = c; - ++count; - } - vTaskDelay(10 / portTICK_PERIOD_MS); - } -} - -void app_main(void) -{ - char line[256]; - char pattern[32]; - char transport[32]; - int repeat = 0; - - ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); - ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); - - esp_log_level_set("*", ESP_LOG_INFO); - esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT_TCP", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT_SSL", ESP_LOG_VERBOSE); - esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE); - esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE); - - ESP_ERROR_CHECK(nvs_flash_init()); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - mqtt_app_start(); - - while (1) { - get_string(line, sizeof(line)); - sscanf(line, "%s %s %d %d %d", transport, pattern, &repeat, &expected_published, &qos_test); - ESP_LOGI(TAG, "PATTERN:%s REPEATED:%d PUBLISHED:%d\n", pattern, repeat, expected_published); - int pattern_size = strlen(pattern); - free(expected_data); - free(actual_data); - actual_published = 0; - expected_size = pattern_size * repeat; - expected_data = malloc(expected_size); - actual_data = malloc(expected_size); - for (int i = 0; i < repeat; i++) { - memcpy(expected_data + i * pattern_size, pattern, pattern_size); - } - printf("EXPECTED STRING %.*s, SIZE:%d\n", expected_size, expected_data, expected_size); - esp_mqtt_client_stop(mqtt_client); - - if (0 == strcmp(transport, "tcp")) { - ESP_LOGI(TAG, "[TCP transport] Startup.."); - esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_TCP_URI); - } else if (0 == strcmp(transport, "ssl")) { - ESP_LOGI(TAG, "[SSL transport] Startup.."); - esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_SSL_URI); - } else if (0 == strcmp(transport, "ws")) { - ESP_LOGI(TAG, "[WS transport] Startup.."); - esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WS_URI); - } else if (0 == strcmp(transport, "wss")) { - ESP_LOGI(TAG, "[WSS transport] Startup.."); - esp_mqtt_client_set_uri(mqtt_client, CONFIG_EXAMPLE_BROKER_WSS_URI); - } else { - ESP_LOGE(TAG, "Unexpected transport"); - abort(); - } - xEventGroupClearBits(mqtt_event_group, CONNECTED_BIT); - esp_mqtt_client_start(mqtt_client); - ESP_LOGI(TAG, "Note free memory: %d bytes", esp_get_free_heap_size()); - xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); - - for (int i = 0; i < expected_published; i++) { - int msg_id = esp_mqtt_client_publish(mqtt_client, CONFIG_EXAMPLE_PUBLISH_TOPIC, expected_data, expected_size, qos_test, 0); - ESP_LOGI(TAG, "[%d] Publishing...", msg_id); - } - } -}