diff --git a/CMakeLists.txt b/CMakeLists.txt index 43798d9..601d484 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,10 +65,15 @@ if(MQTT_C_EXAMPLES) find_package(Threads REQUIRED) if(MQTT_C_OpenSSL_SUPPORT) - add_executable(bio_publisher examples/bio_publisher.c) - target_link_libraries(bio_publisher Threads::Threads mqttc) + if(MSVC) + add_executable(bio_publisher examples/bio_publisher_win.c) + add_executable(openssl_publisher examples/openssl_publisher_win.c) + else() + add_executable(bio_publisher examples/bio_publisher.c) + add_executable(openssl_publisher examples/openssl_publisher.c) + endif() - add_executable(openssl_publisher examples/openssl_publisher.c) + target_link_libraries(bio_publisher Threads::Threads mqttc) target_link_libraries(openssl_publisher Threads::Threads mqttc) elseif(MQTT_C_MbedTLS_SUPPORT) add_executable(mbedtls_publisher examples/mbedtls_publisher.c) diff --git a/examples/bio_publisher_win.c b/examples/bio_publisher_win.c new file mode 100644 index 0000000..cf13bc9 --- /dev/null +++ b/examples/bio_publisher_win.c @@ -0,0 +1,153 @@ + +/** + * @file + * A simple program to that publishes the current time whenever ENTER is pressed. + */ +#include +#include +#include + +#include +#include "templates/bio_sockets.h" + + +/** + * @brief The function that would be called whenever a PUBLISH is received. + * + * @note This function is not used in this example. + */ +void publish_callback(void** unused, struct mqtt_response_publish *published); + +/** + * @brief The client's refresher. This function triggers back-end routines to + * handle ingress/egress traffic to the broker. + * + * @note All this function needs to do is call \ref __mqtt_recv and + * \ref __mqtt_send every so often. I've picked 100 ms meaning that + * client ingress/egress traffic will be handled every 100 ms. + */ +void client_refresher(void* client); + +/** + * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. + */ +void exit_example(int status, BIO* sockfd); + +/** + * A simple program to that publishes the current time whenever ENTER is pressed. + */ +int main(int argc, const char *argv[]) +{ + const char* addr; + const char* port; + const char* topic; + + /* Load OpenSSL */ + SSL_load_error_strings(); + ERR_load_BIO_strings(); + OpenSSL_add_all_algorithms(); + + /* get address (argv[1] if present) */ + if (argc > 1) { + addr = argv[1]; + } else { + addr = "test.mosquitto.org"; + } + + /* get port number (argv[2] if present) */ + if (argc > 2) { + port = argv[2]; + } else { + port = "1883"; + } + + /* get the topic name to publish */ + if (argc > 3) { + topic = argv[3]; + } else { + topic = "datetime"; + } + + /* open the non-blocking TCP socket (connecting to the broker) */ + BIO* sockfd = open_nb_socket(addr, port); + + if (sockfd == NULL) { + exit_example(EXIT_FAILURE, sockfd); + } + + /* setup a client */ + struct mqtt_client client; + uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ + uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ + mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); + mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); + + /* check that we don't have any errors */ + if (client.error != MQTT_OK) { + fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); + exit_example(EXIT_FAILURE, sockfd); + } + + /* start a thread to refresh the client (handle egress and ingree client traffic) */ + if(_beginthread(client_refresher, 0, &client) == -1) { + fprintf(stderr, "Failed to start client daemon.\n"); + exit_example(EXIT_FAILURE, sockfd); + + } + + /* start publishing the time */ + printf("%s is ready to begin publishing the time.\n", argv[0]); + printf("Press ENTER to publish the current time.\n"); + printf("Press CTRL-D (or any other key) to exit.\n\n"); + while(fgetc(stdin) == '\n') { + /* get the current time */ + time_t timer; + time(&timer); + struct tm* tm_info = localtime(&timer); + char timebuf[26]; + strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); + + /* print a message */ + char application_message[256]; + snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); + printf("%s published : \"%s\"", argv[0], application_message); + + /* publish the time */ + mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); + + /* check for errors */ + if (client.error != MQTT_OK) { + fprintf(stderr, "\nerror: %s\n", mqtt_error_str(client.error)); + exit_example(EXIT_FAILURE, sockfd); + } + } + + /* disconnect */ + printf("\n%s disconnecting from %s\n", argv[0], addr); + Sleep(1000); + + /* exit */ + exit_example(EXIT_SUCCESS, sockfd); +} + +void exit_example(int status, BIO* sockfd) +{ + if (sockfd != NULL) BIO_free_all(sockfd); + exit(status); +} + + + +void publish_callback(void** unused, struct mqtt_response_publish *published) +{ + /* not used in this example */ +} + +void client_refresher(void* client) +{ + while(1) + { + mqtt_sync((struct mqtt_client*) client); + Sleep(100); + } +} \ No newline at end of file diff --git a/examples/openssl_publisher_win.c b/examples/openssl_publisher_win.c new file mode 100644 index 0000000..28b3a1f --- /dev/null +++ b/examples/openssl_publisher_win.c @@ -0,0 +1,164 @@ + +/** + * @file + */ +#include +#include +#include + +#include +#include "templates/openssl_sockets.h" + + +/** + * @brief The function that would be called whenever a PUBLISH is received. + * + * @note This function is not used in this example. + */ +void publish_callback(void** unused, struct mqtt_response_publish *published); + +/** + * @brief The client's refresher. This function triggers back-end routines to + * handle ingress/egress traffic to the broker. + * + * @note All this function needs to do is call \ref __mqtt_recv and + * \ref __mqtt_send every so often. I've picked 100 ms meaning that + * client ingress/egress traffic will be handled every 100 ms. + */ +void client_refresher(void* client); + +/** + * @brief Safelty closes the \p sockfd and cancels the \p client_daemon before \c exit. + */ +void exit_example(int status, BIO* sockfd); + +/** + * A simple program to that publishes the current time whenever ENTER is pressed. + */ +int main(int argc, const char *argv[]) +{ + const char* addr; + const char* port; + const char* topic; + const char* ca_file; + + /* Load OpenSSL */ + SSL_load_error_strings(); + ERR_load_BIO_strings(); + OpenSSL_add_all_algorithms(); + SSL_library_init(); + + SSL_CTX* ssl_ctx; + BIO* sockfd; + + if (argc > 1) { + ca_file = argv[1]; + } else { + printf("error: path to the CA certificate to use\n"); + exit(1); + } + + /* get address (argv[2] if present) */ + if (argc > 2) { + addr = argv[2]; + } else { + addr = "test.mosquitto.org"; + } + + /* get port number (argv[3] if present) */ + if (argc > 3) { + port = argv[3]; + } else { + port = "8883"; + } + + /* get the topic name to publish */ + if (argc > 4) { + topic = argv[4]; + } else { + topic = "datetime"; + } + + /* open the non-blocking TCP socket (connecting to the broker) */ + open_nb_socket(&sockfd, &ssl_ctx, addr, port, ca_file, NULL); + + if (sockfd == NULL) { + exit_example(EXIT_FAILURE, sockfd); + } + + /* setup a client */ + struct mqtt_client client; + uint8_t sendbuf[2048]; /* sendbuf should be large enough to hold multiple whole mqtt messages */ + uint8_t recvbuf[1024]; /* recvbuf should be large enough any whole mqtt message expected to be received */ + mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), publish_callback); + mqtt_connect(&client, "publishing_client", NULL, NULL, 0, NULL, NULL, 0, 400); + + /* check that we don't have any errors */ + if (client.error != MQTT_OK) { + fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); + exit_example(EXIT_FAILURE, sockfd); + } + + /* start a thread to refresh the client (handle egress and ingree client traffic) */ + if(_beginthread(client_refresher, 0, &client) == -1) { + fprintf(stderr, "Failed to start client daemon.\n"); + exit_example(EXIT_FAILURE, sockfd); + + } + + /* start publishing the time */ + printf("%s is ready to begin publishing the time.\n", argv[0]); + printf("Press ENTER to publish the current time.\n"); + printf("Press CTRL-D (or any other key) to exit.\n\n"); + while(fgetc(stdin) == '\n') { + /* get the current time */ + time_t timer; + time(&timer); + struct tm* tm_info = localtime(&timer); + char timebuf[26]; + strftime(timebuf, 26, "%Y-%m-%d %H:%M:%S", tm_info); + + /* print a message */ + char application_message[256]; + snprintf(application_message, sizeof(application_message), "The time is %s", timebuf); + printf("%s published : \"%s\"", argv[0], application_message); + + /* publish the time */ + mqtt_publish(&client, topic, application_message, strlen(application_message) + 1, MQTT_PUBLISH_QOS_2); + + /* check for errors */ + if (client.error != MQTT_OK) { + fprintf(stderr, "error: %s\n", mqtt_error_str(client.error)); + exit_example(EXIT_FAILURE, sockfd); + } + } + + /* disconnect */ + printf("\n%s disconnecting from %s\n", argv[0], addr); + Sleep(1000); + + /* exit */ + exit_example(EXIT_SUCCESS, sockfd); +} + +void exit_example(int status, BIO* sockfd) +{ + if (sockfd != NULL) BIO_free_all(sockfd); + exit(status); +} + + + +void publish_callback(void** unused, struct mqtt_response_publish *published) +{ + /* not used in this example */ +} + +void client_refresher(void* client) +{ + while(1) + { + mqtt_sync((struct mqtt_client*) client); + Sleep(100); + } +} \ No newline at end of file