int mqttclient_test(MQTTCtx *mqttCtx) { int rc = MQTT_CODE_SUCCESS, i; switch (mqttCtx->stat) { case WMQ_BEGIN: { PRINTF("MQTT Client: QoS %d, Use TLS %d", mqttCtx->qos, mqttCtx->use_tls); } case WMQ_NET_INIT: { mqttCtx->stat = WMQ_NET_INIT; /* Initialize Network */ rc = MqttClientNet_Init(&mqttCtx->net); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Net Init: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* setup tx/rx buffers */ mqttCtx->tx_buf = (byte*)WOLFMQTT_MALLOC(MAX_BUFFER_SIZE); mqttCtx->rx_buf = (byte*)WOLFMQTT_MALLOC(MAX_BUFFER_SIZE); } case WMQ_INIT: { mqttCtx->stat = WMQ_INIT; /* Initialize MqttClient structure */ rc = MqttClient_Init(&mqttCtx->client, &mqttCtx->net, mqtt_message_cb, mqttCtx->tx_buf, MAX_BUFFER_SIZE, mqttCtx->rx_buf, MAX_BUFFER_SIZE, mqttCtx->cmd_timeout_ms); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Init: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } mqttCtx->client.ctx = mqttCtx; } case WMQ_TCP_CONN: { mqttCtx->stat = WMQ_TCP_CONN; /* Connect to broker */ rc = MqttClient_NetConnect(&mqttCtx->client, mqttCtx->host, mqttCtx->port, DEFAULT_CON_TIMEOUT_MS, mqttCtx->use_tls, mqtt_tls_cb); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Socket Connect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } } case WMQ_MQTT_CONN: { mqttCtx->stat = WMQ_MQTT_CONN; XMEMSET(&mqttCtx->connect, 0, sizeof(MqttConnect)); mqttCtx->connect.keep_alive_sec = mqttCtx->keep_alive_sec; mqttCtx->connect.clean_session = mqttCtx->clean_session; mqttCtx->connect.client_id = mqttCtx->client_id; /* Last will and testament sent by broker to subscribers of topic when broker connection is lost */ XMEMSET(&mqttCtx->lwt_msg, 0, sizeof(mqttCtx->lwt_msg)); mqttCtx->connect.lwt_msg = &mqttCtx->lwt_msg; mqttCtx->connect.enable_lwt = mqttCtx->enable_lwt; if (mqttCtx->enable_lwt) { /* Send client id in LWT payload */ mqttCtx->lwt_msg.qos = mqttCtx->qos; mqttCtx->lwt_msg.retain = 0; mqttCtx->lwt_msg.topic_name = WOLFMQTT_TOPIC_NAME"lwttopic"; mqttCtx->lwt_msg.buffer = (byte*)mqttCtx->client_id; mqttCtx->lwt_msg.total_len = (word16)XSTRLEN(mqttCtx->client_id); } /* Optional authentication */ mqttCtx->connect.username = mqttCtx->username; mqttCtx->connect.password = mqttCtx->password; /* Send Connect and wait for Connect Ack */ rc = MqttClient_Connect(&mqttCtx->client, &mqttCtx->connect); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Connect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto disconn; } /* Validate Connect Ack info */ PRINTF("MQTT Connect Ack: Return Code %u, Session Present %d", mqttCtx->connect.ack.return_code, (mqttCtx->connect.ack.flags & MQTT_CONNECT_ACK_FLAG_SESSION_PRESENT) ? 1 : 0 ); /* Build list of topics */ mqttCtx->topics[0].topic_filter = mqttCtx->topic_name; mqttCtx->topics[0].qos = mqttCtx->qos; /* Subscribe Topic */ XMEMSET(&mqttCtx->subscribe, 0, sizeof(MqttSubscribe)); mqttCtx->subscribe.packet_id = mqtt_get_packetid(); mqttCtx->subscribe.topic_count = sizeof(mqttCtx->topics)/sizeof(MqttTopic); mqttCtx->subscribe.topics = mqttCtx->topics; } case WMQ_SUB: { mqttCtx->stat = WMQ_SUB; rc = MqttClient_Subscribe(&mqttCtx->client, &mqttCtx->subscribe); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Subscribe: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto disconn; } /* show subscribe results */ for (i = 0; i < mqttCtx->subscribe.topic_count; i++) { mqttCtx->topic = &mqttCtx->subscribe.topics[i]; PRINTF(" Topic %s, Qos %u, Return Code %u", mqttCtx->topic->topic_filter, mqttCtx->topic->qos, mqttCtx->topic->return_code); } /* Publish Topic */ XMEMSET(&mqttCtx->publish, 0, sizeof(MqttPublish)); mqttCtx->publish.retain = 0; mqttCtx->publish.qos = mqttCtx->qos; mqttCtx->publish.duplicate = 0; mqttCtx->publish.topic_name = mqttCtx->topic_name; mqttCtx->publish.packet_id = mqtt_get_packetid(); mqttCtx->publish.buffer = (byte*)TEST_MESSAGE; mqttCtx->publish.total_len = (word16)XSTRLEN(TEST_MESSAGE); } case WMQ_PUB: { mqttCtx->stat = WMQ_PUB; rc = MqttClient_Publish(&mqttCtx->client, &mqttCtx->publish); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Publish: Topic %s, %s (%d)", mqttCtx->publish.topic_name, MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto disconn; } /* Read Loop */ PRINTF("MQTT Waiting for message..."); MqttClientNet_CheckForCommand_Enable(&mqttCtx->net); } case WMQ_WAIT_MSG: { mqttCtx->stat = WMQ_WAIT_MSG; do { /* Try and read packet */ rc = MqttClient_WaitMessage(&mqttCtx->client, mqttCtx->cmd_timeout_ms); /* check for test mode */ if (mStopRead) { rc = MQTT_CODE_SUCCESS; break; } /* check return code */ if (rc == MQTT_CODE_CONTINUE) { return rc; } else if (rc == MQTT_CODE_ERROR_TIMEOUT) { /* Check to see if command data (stdin) is available */ rc = MqttClientNet_CheckForCommand(&mqttCtx->net, mqttCtx->rx_buf, MAX_BUFFER_SIZE); if (rc > 0) { /* Publish Topic */ mqttCtx->stat = WMQ_PUB; XMEMSET(&mqttCtx->publish, 0, sizeof(MqttPublish)); mqttCtx->publish.retain = 0; mqttCtx->publish.qos = mqttCtx->qos; mqttCtx->publish.duplicate = 0; mqttCtx->publish.topic_name = mqttCtx->topic_name; mqttCtx->publish.packet_id = mqtt_get_packetid(); mqttCtx->publish.buffer = mqttCtx->rx_buf; mqttCtx->publish.total_len = (word16)rc; rc = MqttClient_Publish(&mqttCtx->client, &mqttCtx->publish); PRINTF("MQTT Publish: Topic %s, %s (%d)", mqttCtx->publish.topic_name, MqttClient_ReturnCodeToString(rc), rc); } /* Keep Alive */ else { rc = MqttClient_Ping(&mqttCtx->client); if (rc == MQTT_CODE_CONTINUE) { return rc; } else if (rc != MQTT_CODE_SUCCESS) { PRINTF("MQTT Ping Keep Alive Error: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); break; } } } else if (rc != MQTT_CODE_SUCCESS) { /* There was an error */ PRINTF("MQTT Message Wait: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); break; } } while (1); /* Check for error */ if (rc != MQTT_CODE_SUCCESS) { goto disconn; } /* Unsubscribe Topics */ XMEMSET(&mqttCtx->unsubscribe, 0, sizeof(MqttUnsubscribe)); mqttCtx->unsubscribe.packet_id = mqtt_get_packetid(); mqttCtx->unsubscribe.topic_count = sizeof(mqttCtx->topics) / sizeof(MqttTopic); mqttCtx->unsubscribe.topics = mqttCtx->topics; } case WMQ_UNSUB: { mqttCtx->stat = WMQ_UNSUB; PRINTF("MQTT Exiting..."); /* Unsubscribe Topics */ rc = MqttClient_Unsubscribe(&mqttCtx->client, &mqttCtx->unsubscribe); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Unsubscribe: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto disconn; } mqttCtx->return_code = rc; } case WMQ_DISCONNECT: { /* Disconnect */ rc = MqttClient_Disconnect(&mqttCtx->client); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Disconnect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto disconn; } } case WMQ_NET_DISCONNECT: { mqttCtx->stat = WMQ_NET_DISCONNECT; rc = MqttClient_NetDisconnect(&mqttCtx->client); if (rc == MQTT_CODE_CONTINUE) { return rc; } PRINTF("MQTT Socket Disconnect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); } case WMQ_DONE: { mqttCtx->stat = WMQ_DONE; rc = mqttCtx->return_code; goto exit; } default: rc = MQTT_CODE_ERROR_STAT; goto exit; } /* switch */ disconn: mqttCtx->stat = WMQ_NET_DISCONNECT; mqttCtx->return_code = rc; return MQTT_CODE_CONTINUE; exit: /* Free resources */ if (mqttCtx->tx_buf) WOLFMQTT_FREE(mqttCtx->tx_buf); if (mqttCtx->rx_buf) WOLFMQTT_FREE(mqttCtx->rx_buf); /* Cleanup network */ MqttClientNet_DeInit(&mqttCtx->net); return rc; }
int mqttclient_test(void* args) { int rc; MqttClient client; MqttNet net; word16 port = 0; const char* host = DEFAULT_MQTT_HOST; int use_tls = 0; MqttQoS qos = DEFAULT_MQTT_QOS; byte clean_session = 1; word16 keep_alive_sec = DEFAULT_KEEP_ALIVE_SEC; const char* client_id = DEFAULT_CLIENT_ID; int enable_lwt = 0; const char* username = NULL; const char* password = NULL; byte *tx_buf = NULL, *rx_buf = NULL; const char* topicName = DEFAULT_TOPIC_NAME; word32 cmd_timeout_ms = DEFAULT_CMD_TIMEOUT_MS; byte test_mode = 0; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = -1; /* error state */ while ((rc = mygetopt(argc, argv, "?h:p:tc:q:sk:i:lu:w:n:C:T")) != -1) { switch ((char)rc) { case '?' : Usage(); exit(EXIT_SUCCESS); case 'h' : host = myoptarg; break; case 'p' : port = (word16)XATOI(myoptarg); if (port == 0) { return err_sys("Invalid Port Number!"); } break; case 't': use_tls = 1; break; case 'c': mTlsFile = myoptarg; break; case 'q' : qos = (MqttQoS)((byte)XATOI(myoptarg)); if (qos > MQTT_QOS_2) { return err_sys("Invalid QoS value!"); } break; case 's': clean_session = 0; break; case 'k': keep_alive_sec = XATOI(myoptarg); break; case 'i': client_id = myoptarg; break; case 'l': enable_lwt = 1; break; case 'u': username = myoptarg; break; case 'w': password = myoptarg; break; case 'n': topicName = myoptarg; break; case 'C': cmd_timeout_ms = XATOI(myoptarg); break; case 'T': test_mode = 1; break; default: Usage(); exit(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ /* Start example MQTT Client */ PRINTF("MQTT Client: QoS %d", qos); /* Initialize Network */ rc = MqttClientNet_Init(&net); PRINTF("MQTT Net Init: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* Initialize MqttClient structure */ tx_buf = (byte*)WOLFMQTT_MALLOC(MAX_BUFFER_SIZE); rx_buf = (byte*)WOLFMQTT_MALLOC(MAX_BUFFER_SIZE); rc = MqttClient_Init(&client, &net, mqttclient_message_cb, tx_buf, MAX_BUFFER_SIZE, rx_buf, MAX_BUFFER_SIZE, cmd_timeout_ms); PRINTF("MQTT Init: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* Connect to broker */ rc = MqttClient_NetConnect(&client, host, port, DEFAULT_CON_TIMEOUT_MS, use_tls, mqttclient_tls_cb); PRINTF("MQTT Socket Connect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc == MQTT_CODE_SUCCESS) { /* Define connect parameters */ MqttConnect connect; MqttMessage lwt_msg; XMEMSET(&connect, 0, sizeof(MqttConnect)); connect.keep_alive_sec = keep_alive_sec; connect.clean_session = clean_session; connect.client_id = client_id; /* Last will and testament sent by broker to subscribers of topic when broker connection is lost */ XMEMSET(&lwt_msg, 0, sizeof(lwt_msg)); connect.lwt_msg = &lwt_msg; connect.enable_lwt = enable_lwt; if (enable_lwt) { /* Send client id in LWT payload */ lwt_msg.qos = qos; lwt_msg.retain = 0; lwt_msg.topic_name = WOLFMQTT_TOPIC_NAME"lwttopic"; lwt_msg.buffer = (byte*)client_id; lwt_msg.total_len = (word16)XSTRLEN(client_id); } /* Optional authentication */ connect.username = username; connect.password = password; /* Send Connect and wait for Connect Ack */ rc = MqttClient_Connect(&client, &connect); PRINTF("MQTT Connect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc == MQTT_CODE_SUCCESS) { MqttSubscribe subscribe; MqttUnsubscribe unsubscribe; MqttTopic topics[1], *topic; MqttPublish publish; int i; /* Build list of topics */ topics[0].topic_filter = topicName; topics[0].qos = qos; /* Validate Connect Ack info */ PRINTF("MQTT Connect Ack: Return Code %u, Session Present %d", connect.ack.return_code, (connect.ack.flags & MQTT_CONNECT_ACK_FLAG_SESSION_PRESENT) ? 1 : 0 ); /* Subscribe Topic */ XMEMSET(&subscribe, 0, sizeof(MqttSubscribe)); subscribe.packet_id = mqttclient_get_packetid(); subscribe.topic_count = sizeof(topics)/sizeof(MqttTopic); subscribe.topics = topics; rc = MqttClient_Subscribe(&client, &subscribe); PRINTF("MQTT Subscribe: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } for (i = 0; i < subscribe.topic_count; i++) { topic = &subscribe.topics[i]; PRINTF(" Topic %s, Qos %u, Return Code %u", topic->topic_filter, topic->qos, topic->return_code); } /* Publish Topic */ XMEMSET(&publish, 0, sizeof(MqttPublish)); publish.retain = 0; publish.qos = qos; publish.duplicate = 0; publish.topic_name = topicName; publish.packet_id = mqttclient_get_packetid(); publish.buffer = (byte*)TEST_MESSAGE; publish.total_len = (word16)XSTRLEN(TEST_MESSAGE); rc = MqttClient_Publish(&client, &publish); PRINTF("MQTT Publish: Topic %s, %s (%d)", publish.topic_name, MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* Read Loop */ PRINTF("MQTT Waiting for message..."); while (mStopRead == 0) { /* Try and read packet */ rc = MqttClient_WaitMessage(&client, cmd_timeout_ms); if (rc == MQTT_CODE_ERROR_TIMEOUT) { /* Check to see if command data (stdin) is available */ rc = MqttClientNet_CheckForCommand(&net, rx_buf, MAX_BUFFER_SIZE); if (rc > 0) { /* Publish Topic */ XMEMSET(&publish, 0, sizeof(MqttPublish)); publish.retain = 0; publish.qos = qos; publish.duplicate = 0; publish.topic_name = topicName; publish.packet_id = mqttclient_get_packetid(); publish.buffer = rx_buf; publish.total_len = (word16)rc; rc = MqttClient_Publish(&client, &publish); PRINTF("MQTT Publish: Topic %s, %s (%d)", publish.topic_name, MqttClient_ReturnCodeToString(rc), rc); } /* Keep Alive */ else { rc = MqttClient_Ping(&client); if (rc != MQTT_CODE_SUCCESS) { PRINTF("MQTT Ping Keep Alive Error: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); break; } } } else if (rc != MQTT_CODE_SUCCESS) { /* There was an error */ PRINTF("MQTT Message Wait: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); break; } /* Exit if test mode */ if (test_mode) { break; } } /* Check for error */ if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* Unsubscribe Topics */ XMEMSET(&unsubscribe, 0, sizeof(MqttUnsubscribe)); unsubscribe.packet_id = mqttclient_get_packetid(); unsubscribe.topic_count = sizeof(topics)/sizeof(MqttTopic); unsubscribe.topics = topics; rc = MqttClient_Unsubscribe(&client, &unsubscribe); PRINTF("MQTT Unsubscribe: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); if (rc != MQTT_CODE_SUCCESS) { goto exit; } /* Disconnect */ rc = MqttClient_Disconnect(&client); PRINTF("MQTT Disconnect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); } rc = MqttClient_NetDisconnect(&client); PRINTF("MQTT Socket Disconnect: %s (%d)", MqttClient_ReturnCodeToString(rc), rc); } exit: /* Free resources */ if (tx_buf) WOLFMQTT_FREE(tx_buf); if (rx_buf) WOLFMQTT_FREE(rx_buf); /* Cleanup network */ MqttClientNet_DeInit(&net); /* Set return code */ ((func_args*)args)->return_code = (rc == 0) ? 0 : EXIT_FAILURE; return 0; }