diff --git a/examples/mqttexample.h b/examples/mqttexample.h index d35178f7..ca3799e8 100644 --- a/examples/mqttexample.h +++ b/examples/mqttexample.h @@ -200,6 +200,9 @@ typedef struct _MQTTCtx { unsigned int useNonBlockMode:1; /* set to use non-blocking mode. network callbacks can return MQTT_CODE_CONTINUE to indicate "would block" */ #endif +#ifdef WOLFMQTT_WOLFIP + struct wolfIP *stack; /* wolfIP TCP/IP stack instance */ +#endif } MQTTCtx; diff --git a/examples/mqttnet.c b/examples/mqttnet.c index dd36d5cb..c829eb4c 100644 --- a/examples/mqttnet.c +++ b/examples/mqttnet.c @@ -1157,6 +1157,132 @@ static int NetDisconnect(void *context) return 0; } +/* -------------------------------------------------------------------------- */ +/* WOLFIP TCP/IP STACK NETWORK CALLBACK EXAMPLE */ +/* -------------------------------------------------------------------------- */ +#elif defined(WOLFMQTT_WOLFIP) + +static int NetDisconnect(void *context) +{ + SocketContext *sock = (SocketContext*)context; + if (sock) { + if (sock->fd != SOCKET_INVALID) { + wolfIP_sock_close(sock->stack, sock->fd); + sock->fd = SOCKET_INVALID; + } + sock->stat = SOCK_BEGIN; + } + return 0; +} + +static int NetConnect(void *context, const char* host, word16 port, + int timeout_ms) +{ + SocketContext *sock = (SocketContext*)context; + struct wolfIP_sockaddr_in addr; + int rc; + + (void)timeout_ms; + + if (context == NULL || host == NULL) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + switch (sock->stat) { + case SOCK_BEGIN: + { + /* Create TCP socket */ + sock->fd = wolfIP_sock_socket(sock->stack, AF_INET, + IPSTACK_SOCK_STREAM, 0); + if (sock->fd < 0) { + return MQTT_CODE_ERROR_NETWORK; + } + + sock->stat = SOCK_CONN; + } + FALL_THROUGH; + + case SOCK_CONN: + { + /* Set up address and initiate connect. + * Note: atoip4() only supports dotted-quad IPv4 strings + * (e.g., "192.168.1.1") and does not resolve DNS hostnames. */ + XMEMSET(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = ee16(port); + addr.sin_addr.s_addr = atoip4(host); + if (addr.sin_addr.s_addr == 0) { + NetDisconnect(context); + return MQTT_CODE_ERROR_BAD_ARG; + } + + rc = wolfIP_sock_connect(sock->stack, sock->fd, + (struct wolfIP_sockaddr *)&addr, sizeof(addr)); + if (rc == 0) { + return MQTT_CODE_SUCCESS; + } + if (rc == -WOLFIP_EAGAIN) { + return MQTT_CODE_CONTINUE; + } + + /* Connection failed */ + NetDisconnect(context); + return MQTT_CODE_ERROR_NETWORK; + } + + default: + break; + } + + return MQTT_CODE_ERROR_NETWORK; +} + +static int NetRead(void *context, byte* buf, int buf_len, int timeout_ms) +{ + SocketContext *sock = (SocketContext*)context; + int rc; + + (void)timeout_ms; + + if (context == NULL || buf == NULL || buf_len <= 0) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + rc = wolfIP_sock_recv(sock->stack, sock->fd, buf, buf_len, 0); + /* -WOLFIP_EAGAIN: no data yet; -1: socket not yet in ESTABLISHED state */ + if (rc == -WOLFIP_EAGAIN || rc == -1) { + return MQTT_CODE_CONTINUE; + } + if (rc <= 0) { + return MQTT_CODE_ERROR_NETWORK; + } + return rc; +} + +static int NetWrite(void *context, const byte* buf, int buf_len, + int timeout_ms) +{ + SocketContext *sock = (SocketContext*)context; + int rc; + + (void)timeout_ms; + + if (context == NULL || buf == NULL || buf_len <= 0) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + rc = wolfIP_sock_send(sock->stack, sock->fd, buf, buf_len, 0); + /* -WOLFIP_EAGAIN: send buffer full; -1: socket not yet in ESTABLISHED state */ + if (rc == -WOLFIP_EAGAIN || rc == -1) { + return MQTT_CODE_CONTINUE; + } + if (rc <= 0) { + return MQTT_CODE_ERROR_NETWORK; + } + return rc; +} + + /* -------------------------------------------------------------------------- */ /* GENERIC BSD SOCKET TCP NETWORK CALLBACK EXAMPLE */ /* -------------------------------------------------------------------------- */ @@ -1807,6 +1933,11 @@ int MqttClientNet_Init(MqttNet* net, MQTTCtx* mqttCtx) #endif sockCtx->stat = SOCK_BEGIN; sockCtx->mqttCtx = mqttCtx; + #ifdef WOLFMQTT_WOLFIP + if (mqttCtx != NULL) { + sockCtx->stack = mqttCtx->stack; + } + #endif #if defined(WOLFMQTT_MULTITHREAD) && defined(WOLFMQTT_ENABLE_STDIN_CAP) /* setup the pipe for waking select() */ diff --git a/examples/mqttnet.h b/examples/mqttnet.h index 7bfd1aaa..c9ca0bed 100644 --- a/examples/mqttnet.h +++ b/examples/mqttnet.h @@ -70,6 +70,9 @@ typedef struct _SocketContext { NX_IP *ipPtr; NX_PACKET *nxPacket; ULONG nxOffset; +#endif +#ifdef WOLFMQTT_WOLFIP + struct wolfIP *stack; #endif MQTTCtx* mqttCtx; } SocketContext; diff --git a/examples/mqttport.h b/examples/mqttport.h index 571453eb..4a062b78 100644 --- a/examples/mqttport.h +++ b/examples/mqttport.h @@ -73,6 +73,19 @@ extern "C" { #include "lwip/sockets.h" #include "lwip/netdb.h" +/* wolfIP TCP/IP stack */ +#elif defined(WOLFMQTT_WOLFIP) + #include "wolfip.h" + + #define SOCKET_T int + #define SOCKET_INVALID (-1) + #define SOCK_ADDR_IN struct wolfIP_sockaddr_in + /* For wolfIP targets without filesystem support, define NO_FILESYSTEM + * via build configuration (e.g., compiler flags or user_settings.h). */ + #ifndef NO_FILESYSTEM + #define NO_FILESYSTEM + #endif + /* User defined IO */ #elif defined(WOLFMQTT_USER_IO) #include "userio_template.h" diff --git a/src/mqtt_broker.c b/src/mqtt_broker.c index a038376d..57b837d6 100644 --- a/src/mqtt_broker.c +++ b/src/mqtt_broker.c @@ -36,9 +36,11 @@ #ifdef WOLFMQTT_BROKER /* -------------------------------------------------------------------------- */ -/* Platform includes - only for default POSIX backend */ +/* Platform includes */ /* -------------------------------------------------------------------------- */ -#ifndef WOLFMQTT_BROKER_CUSTOM_NET +#if defined(WOLFMQTT_WOLFIP) + #include "wolfip.h" +#elif !defined(WOLFMQTT_BROKER_CUSTOM_NET) #include #include #include @@ -47,21 +49,34 @@ #include #include #include -#endif /* !WOLFMQTT_BROKER_CUSTOM_NET */ +#endif /* -------------------------------------------------------------------------- */ /* Default time abstraction */ /* -------------------------------------------------------------------------- */ #ifndef WOLFMQTT_BROKER_GET_TIME_S - #define WOLFMQTT_BROKER_GET_TIME_S() \ - ((WOLFMQTT_BROKER_TIME_T)time(NULL)) + #if defined(WOLFMQTT_WOLFIP) + /* wolfIP has no default time source. Define + * WOLFMQTT_BROKER_GET_TIME_S in user_settings.h to provide one. + * Example: #define WOLFMQTT_BROKER_GET_TIME_S() myGetTimeSec() */ + #error "WOLFMQTT_WOLFIP requires WOLFMQTT_BROKER_GET_TIME_S to be defined" + #else + #define WOLFMQTT_BROKER_GET_TIME_S() \ + ((WOLFMQTT_BROKER_TIME_T)time(NULL)) + #endif #endif /* -------------------------------------------------------------------------- */ /* Default sleep abstraction */ /* -------------------------------------------------------------------------- */ #ifndef BROKER_SLEEP_MS - #ifdef USE_WINDOWS_API + #if defined(WOLFMQTT_WOLFIP) + /* No-op: wolfIP uses cooperative scheduling via MqttBroker_Step(). + * Do not use MqttBroker_Run() on wolfIP - it will busy-spin. + * Override BROKER_SLEEP_MS in user_settings.h if a yield/delay + * primitive is available on your platform. */ + #define BROKER_SLEEP_MS(ms) do {} while(0) + #elif defined(USE_WINDOWS_API) #define BROKER_SLEEP_MS(ms) Sleep(ms) #else #define BROKER_SLEEP_MS(ms) usleep((unsigned)(ms) * 1000) @@ -170,10 +185,281 @@ static void BrokerStore_String(char** dst_ptr, BrokerStore_String(&(dst), src, len) #endif +#ifdef ENABLE_MQTT_TLS +static int BrokerTls_Init(MqttBroker* broker) +{ + WOLFSSL_CTX* ctx = NULL; + int wolf_rc; /* wolfSSL return codes (compared against WOLFSSL_SUCCESS) */ + int mqtt_rc = MQTT_CODE_SUCCESS; /* normalized MQTT return code */ + + wolf_rc = wolfSSL_Init(); + if (wolf_rc != WOLFSSL_SUCCESS) { + WBLOG_ERR(broker, "broker: wolfSSL_Init failed %d", wolf_rc); + return MQTT_CODE_ERROR_BAD_ARG; + } + + /* Select TLS method based on version preference */ + if (broker->tls_version == 12) { + ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + } + else if (broker->tls_version == 13) { + ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + } + else { + ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); + } + if (ctx == NULL) { + WBLOG_ERR(broker, "broker: wolfSSL_CTX_new failed"); + mqtt_rc = MQTT_CODE_ERROR_MEMORY; + } + + /* Load server certificate */ + if (mqtt_rc == MQTT_CODE_SUCCESS) { + if (broker->tls_cert == NULL) { + WBLOG_ERR(broker, "broker: TLS cert not set (-c)"); + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; + } + } + if (mqtt_rc == MQTT_CODE_SUCCESS) { +#ifndef NO_FILESYSTEM + wolf_rc = wolfSSL_CTX_use_certificate_file(ctx, broker->tls_cert, + WOLFSSL_FILETYPE_PEM); + if (wolf_rc != WOLFSSL_SUCCESS) { + WBLOG_ERR(broker, "broker: load cert failed %d (%s)", + wolf_rc, broker->tls_cert); + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; + } +#else + /* File operations not available in NO_FILESYSTEM builds */ + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; +#endif + } + + /* Load server private key */ + if (mqtt_rc == MQTT_CODE_SUCCESS) { + if (broker->tls_key == NULL) { + WBLOG_ERR(broker, "broker: TLS key not set (-K)"); + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; + } + } + if (mqtt_rc == MQTT_CODE_SUCCESS) { +#ifndef NO_FILESYSTEM + wolf_rc = wolfSSL_CTX_use_PrivateKey_file(ctx, broker->tls_key, + WOLFSSL_FILETYPE_PEM); + if (wolf_rc != WOLFSSL_SUCCESS) { + WBLOG_ERR(broker, "broker: load key failed %d (%s)", + wolf_rc, broker->tls_key); + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; + } +#else + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; +#endif + } + + /* Set wolfSSL IO callbacks */ + if (mqtt_rc == MQTT_CODE_SUCCESS) { + wolfSSL_CTX_SetIORecv(ctx, MqttSocket_TlsSocketReceive); + wolfSSL_CTX_SetIOSend(ctx, MqttSocket_TlsSocketSend); + } + + /* Mutual TLS: load CA and require client certificate */ + if (mqtt_rc == MQTT_CODE_SUCCESS && broker->tls_ca != NULL) { +#ifndef NO_FILESYSTEM + wolf_rc = wolfSSL_CTX_load_verify_locations(ctx, broker->tls_ca, + NULL); + if (wolf_rc != WOLFSSL_SUCCESS) { + WBLOG_ERR(broker, "broker: load CA failed %d (%s)", + wolf_rc, broker->tls_ca); + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; + } +#else + mqtt_rc = MQTT_CODE_ERROR_BAD_ARG; +#endif + if (mqtt_rc == MQTT_CODE_SUCCESS) { + wolfSSL_CTX_set_verify(ctx, + WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, + NULL); + WBLOG_INFO(broker, "broker: mutual TLS enabled (CA=%s)", + broker->tls_ca); + } + } + + if (mqtt_rc == MQTT_CODE_SUCCESS) { + broker->tls_ctx = ctx; + broker->tls_ctx_owned = 1; + } + else { + if (ctx != NULL) { + wolfSSL_CTX_free(ctx); + } + wolfSSL_Cleanup(); + } + return mqtt_rc; +} + +static void BrokerTls_Free(MqttBroker* broker) +{ + if (broker->tls_ctx != NULL) { + wolfSSL_CTX_free(broker->tls_ctx); + broker->tls_ctx = NULL; + } + wolfSSL_Cleanup(); +} +#endif /* ENABLE_MQTT_TLS */ + +/* -------------------------------------------------------------------------- */ +/* wolfIP network backend */ +/* -------------------------------------------------------------------------- */ +#if defined(WOLFMQTT_WOLFIP) + +/* Context passed through MqttBrokerNet.ctx */ +#ifndef WOLFMQTT_WOLFIP_CTX_DEFINED +#define WOLFMQTT_WOLFIP_CTX_DEFINED +typedef struct BrokerWolfIP_Ctx { + struct wolfIP *stack; +} BrokerWolfIP_Ctx; +#endif + +/* Single-instance context: wolfIP targets are typically embedded systems + * with one broker instance. For multiple instances, use + * WOLFMQTT_BROKER_CUSTOM_NET and provide per-instance context. */ +static BrokerWolfIP_Ctx broker_wolfip_ctx; + +static int BrokerWolfIP_Listen(void* ctx, BROKER_SOCKET_T* sock, + word16 port, int backlog) +{ + BrokerWolfIP_Ctx* wctx = (BrokerWolfIP_Ctx*)ctx; + struct wolfIP_sockaddr_in addr; + BROKER_SOCKET_T fd; + + if (wctx == NULL || wctx->stack == NULL || sock == NULL) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + fd = wolfIP_sock_socket(wctx->stack, AF_INET, IPSTACK_SOCK_STREAM, 0); + if (fd < 0) { + return MQTT_CODE_ERROR_NETWORK; + } + + XMEMSET(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = ee16(port); + addr.sin_addr.s_addr = 0; /* INADDR_ANY */ + + if (wolfIP_sock_bind(wctx->stack, fd, + (struct wolfIP_sockaddr*)&addr, sizeof(addr)) < 0) { + wolfIP_sock_close(wctx->stack, fd); + return MQTT_CODE_ERROR_NETWORK; + } + if (wolfIP_sock_listen(wctx->stack, fd, backlog) < 0) { + wolfIP_sock_close(wctx->stack, fd); + return MQTT_CODE_ERROR_NETWORK; + } + + *sock = fd; + return MQTT_CODE_SUCCESS; +} + +static int BrokerWolfIP_Accept(void* ctx, BROKER_SOCKET_T listen_sock, + BROKER_SOCKET_T* client_sock) +{ + BrokerWolfIP_Ctx* wctx = (BrokerWolfIP_Ctx*)ctx; + BROKER_SOCKET_T fd; + + if (wctx == NULL || wctx->stack == NULL || client_sock == NULL) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + fd = wolfIP_sock_accept(wctx->stack, listen_sock, NULL, NULL); + if (fd == -WOLFIP_EAGAIN) { + /* No pending connection */ + return MQTT_CODE_CONTINUE; + } + if (fd < 0) { + return MQTT_CODE_ERROR_NETWORK; + } + + *client_sock = fd; + return MQTT_CODE_SUCCESS; +} + +static int BrokerWolfIP_Read(void* ctx, BROKER_SOCKET_T sock, + byte* buf, int buf_len, int timeout_ms) +{ + BrokerWolfIP_Ctx* wctx = (BrokerWolfIP_Ctx*)ctx; + int rc; + (void)timeout_ms; + + if (wctx == NULL || wctx->stack == NULL || buf == NULL || buf_len <= 0) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + rc = wolfIP_sock_recv(wctx->stack, sock, buf, (size_t)buf_len, 0); + /* -WOLFIP_EAGAIN: no data yet; -1: socket not yet in ESTABLISHED state */ + if (rc == -WOLFIP_EAGAIN || rc == -1) { + return MQTT_CODE_CONTINUE; + } + if (rc <= 0) { + return MQTT_CODE_ERROR_NETWORK; + } + return rc; +} + +static int BrokerWolfIP_Write(void* ctx, BROKER_SOCKET_T sock, + const byte* buf, int buf_len, int timeout_ms) +{ + BrokerWolfIP_Ctx* wctx = (BrokerWolfIP_Ctx*)ctx; + int rc; + (void)timeout_ms; + + if (wctx == NULL || wctx->stack == NULL || buf == NULL || buf_len <= 0) { + return MQTT_CODE_ERROR_BAD_ARG; + } + + rc = wolfIP_sock_send(wctx->stack, sock, buf, (size_t)buf_len, 0); + /* -WOLFIP_EAGAIN: send buffer full; -1: socket not yet in ESTABLISHED state */ + if (rc == -WOLFIP_EAGAIN || rc == -1) { + return MQTT_CODE_CONTINUE; + } + if (rc <= 0) { + return MQTT_CODE_ERROR_NETWORK; + } + return rc; +} + +static int BrokerWolfIP_Close(void* ctx, BROKER_SOCKET_T sock) +{ + BrokerWolfIP_Ctx* wctx = (BrokerWolfIP_Ctx*)ctx; + + if (wctx != NULL && wctx->stack != NULL && + sock != BROKER_SOCKET_INVALID) { + wolfIP_sock_close(wctx->stack, sock); + } + return MQTT_CODE_SUCCESS; +} + +int MqttBrokerNet_wolfIP_Init(MqttBrokerNet* net, void* wolfIP_stack) +{ + if (net == NULL || wolfIP_stack == NULL) { + return MQTT_CODE_ERROR_BAD_ARG; + } + XMEMSET(net, 0, sizeof(*net)); + XMEMSET(&broker_wolfip_ctx, 0, sizeof(broker_wolfip_ctx)); + broker_wolfip_ctx.stack = (struct wolfIP*)wolfIP_stack; + + net->listen = BrokerWolfIP_Listen; + net->accept = BrokerWolfIP_Accept; + net->read = BrokerWolfIP_Read; + net->write = BrokerWolfIP_Write; + net->close = BrokerWolfIP_Close; + net->ctx = &broker_wolfip_ctx; + return MQTT_CODE_SUCCESS; +} + /* -------------------------------------------------------------------------- */ /* Default POSIX network backend */ /* -------------------------------------------------------------------------- */ -#ifndef WOLFMQTT_BROKER_CUSTOM_NET +#elif !defined(WOLFMQTT_BROKER_CUSTOM_NET) static int BrokerPosix_SetNonBlocking(BROKER_SOCKET_T fd) { @@ -351,112 +637,9 @@ int MqttBrokerNet_Init(MqttBrokerNet* net) return MQTT_CODE_SUCCESS; } -#ifdef ENABLE_MQTT_TLS -static int BrokerTls_Init(MqttBroker* broker) -{ - WOLFSSL_CTX* ctx = NULL; - int rc; - - rc = wolfSSL_Init(); - if (rc != WOLFSSL_SUCCESS) { - WBLOG_ERR(broker, "broker: wolfSSL_Init failed %d", rc); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - - /* Select TLS method based on version preference */ - if (rc == WOLFSSL_SUCCESS) { - if (broker->tls_version == 12) { - ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); - } - else if (broker->tls_version == 13) { - ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); - } - else { - ctx = wolfSSL_CTX_new(wolfSSLv23_server_method()); - } - if (ctx == NULL) { - WBLOG_ERR(broker, "broker: wolfSSL_CTX_new failed"); - rc = MQTT_CODE_ERROR_MEMORY; - } - } - - /* Load server certificate */ - if (rc == WOLFSSL_SUCCESS) { - if (broker->tls_cert == NULL) { - WBLOG_ERR(broker, "broker: TLS cert not set (-c)"); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - } - if (rc == WOLFSSL_SUCCESS) { - rc = wolfSSL_CTX_use_certificate_file(ctx, broker->tls_cert, - WOLFSSL_FILETYPE_PEM); - if (rc != WOLFSSL_SUCCESS) { - WBLOG_ERR(broker, "broker: load cert failed %d (%s)", rc, broker->tls_cert); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - } - - /* Load server private key */ - if (rc == WOLFSSL_SUCCESS) { - if (broker->tls_key == NULL) { - WBLOG_ERR(broker, "broker: TLS key not set (-K)"); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - } - if (rc == WOLFSSL_SUCCESS) { - rc = wolfSSL_CTX_use_PrivateKey_file(ctx, broker->tls_key, - WOLFSSL_FILETYPE_PEM); - if (rc != WOLFSSL_SUCCESS) { - WBLOG_ERR(broker, "broker: load key failed %d (%s)", rc, broker->tls_key); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - } - - /* Set wolfSSL IO callbacks */ - if (rc == WOLFSSL_SUCCESS) { - wolfSSL_CTX_SetIORecv(ctx, MqttSocket_TlsSocketReceive); - wolfSSL_CTX_SetIOSend(ctx, MqttSocket_TlsSocketSend); - } - - /* Mutual TLS: load CA and require client certificate */ - if (rc == WOLFSSL_SUCCESS && broker->tls_ca != NULL) { - rc = wolfSSL_CTX_load_verify_locations(ctx, broker->tls_ca, NULL); - if (rc != WOLFSSL_SUCCESS) { - WBLOG_ERR(broker, "broker: load CA failed %d (%s)", rc, broker->tls_ca); - rc = MQTT_CODE_ERROR_BAD_ARG; - } - else { - wolfSSL_CTX_set_verify(ctx, - WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, - NULL); - WBLOG_INFO(broker, "broker: mutual TLS enabled (CA=%s)", broker->tls_ca); - } - } - - if (rc == WOLFSSL_SUCCESS) { - broker->tls_ctx = ctx; - rc = MQTT_CODE_SUCCESS; - } - else { - if (ctx != NULL) { - wolfSSL_CTX_free(ctx); - } - wolfSSL_Cleanup(); - } - return rc; -} -static void BrokerTls_Free(MqttBroker* broker) -{ - if (broker->tls_ctx != NULL) { - wolfSSL_CTX_free(broker->tls_ctx); - broker->tls_ctx = NULL; - } - wolfSSL_Cleanup(); -} -#endif /* ENABLE_MQTT_TLS */ -#endif /* !WOLFMQTT_BROKER_CUSTOM_NET */ +#endif /* WOLFMQTT_WOLFIP / !WOLFMQTT_BROKER_CUSTOM_NET */ /* -------------------------------------------------------------------------- */ /* WebSocket server support (libwebsockets) */ @@ -3233,7 +3416,7 @@ int MqttBroker_Init(MqttBroker* broker, MqttBrokerNet* net) broker->log_level = BROKER_LOG_LEVEL_DEFAULT; broker->next_packet_id = 1; -#ifndef WOLFMQTT_BROKER_CUSTOM_NET +#if !defined(WOLFMQTT_WOLFIP) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) /* For the default POSIX backend, the net callbacks expect ctx to be a * MqttBroker* for logging via WBLOG_*. If no context was provided, * default to using this broker instance to avoid NULL-dereference. */ @@ -3381,7 +3564,7 @@ int MqttBroker_Step(MqttBroker* broker) return activity ? MQTT_CODE_SUCCESS : MQTT_CODE_CONTINUE; } -int MqttBroker_Run(MqttBroker* broker) +int MqttBroker_Start(MqttBroker* broker) { int rc; @@ -3475,6 +3658,18 @@ int MqttBroker_Run(MqttBroker* broker) #endif broker->running = 1; + return MQTT_CODE_SUCCESS; +} + +int MqttBroker_Run(MqttBroker* broker) +{ + int rc; + + rc = MqttBroker_Start(broker); + if (rc != MQTT_CODE_SUCCESS) { + return rc; + } + while (broker->running) { rc = MqttBroker_Step(broker); if (rc == MQTT_CODE_CONTINUE) { @@ -3526,8 +3721,19 @@ int MqttBroker_Free(MqttBroker* broker) BrokerPendingWill_FreeAll(broker); BrokerRetained_FreeAll(broker); -#if defined(ENABLE_MQTT_TLS) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) - BrokerTls_Free(broker); +#ifdef ENABLE_MQTT_TLS + if (broker->tls_ctx != NULL) { + if (broker->tls_ctx_owned) { + /* Context was created by BrokerTls_Init: full cleanup */ + BrokerTls_Free(broker); + } + else { + /* Application-provided TLS context: free ctx but skip + * wolfSSL_Cleanup() since wolfSSL may be shared */ + wolfSSL_CTX_free(broker->tls_ctx); + broker->tls_ctx = NULL; + } + } #endif /* Close listen sockets */ @@ -3554,6 +3760,7 @@ int MqttBroker_Free(MqttBroker* broker) /* -------------------------------------------------------------------------- */ static void BrokerUsage(const char* prog) { + (void)prog; /* Suppress unused parameter warning */ PRINTF("usage: %s [-p port] [-v level]" #ifdef WOLFMQTT_BROKER_AUTH " [-u user] [-P pass]" @@ -3605,7 +3812,8 @@ static void BrokerUsage(const char* prog) static MqttBroker* g_broker = NULL; -#if !defined(WOLFMQTT_BROKER_CUSTOM_NET) && !defined(NO_MAIN_DRIVER) +#if !defined(WOLFMQTT_WOLFIP) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) && \ + !defined(NO_MAIN_DRIVER) #include static void broker_signal_handler(int signo) { @@ -3628,7 +3836,11 @@ int wolfmqtt_broker(int argc, char** argv) setvbuf(stdout, NULL, _IONBF, 0); #endif -#ifndef WOLFMQTT_BROKER_CUSTOM_NET +#if defined(WOLFMQTT_WOLFIP) + XMEMSET(&net, 0, sizeof(net)); + PRINTF("broker: use MqttBrokerNet_wolfIP_Init() for wolfIP"); + return MQTT_CODE_ERROR_BAD_ARG; +#elif !defined(WOLFMQTT_BROKER_CUSTOM_NET) rc = MqttBrokerNet_Init(&net); if (rc != MQTT_CODE_SUCCESS) { return rc; @@ -3696,7 +3908,8 @@ int wolfmqtt_broker(int argc, char** argv) } } -#if !defined(WOLFMQTT_BROKER_CUSTOM_NET) && !defined(NO_MAIN_DRIVER) +#if !defined(WOLFMQTT_WOLFIP) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) && \ + !defined(NO_MAIN_DRIVER) g_broker = &broker; signal(SIGINT, broker_signal_handler); signal(SIGTERM, broker_signal_handler); @@ -3704,7 +3917,8 @@ int wolfmqtt_broker(int argc, char** argv) rc = MqttBroker_Run(&broker); -#if !defined(WOLFMQTT_BROKER_CUSTOM_NET) && !defined(NO_MAIN_DRIVER) +#if !defined(WOLFMQTT_WOLFIP) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) && \ + !defined(NO_MAIN_DRIVER) g_broker = NULL; #endif diff --git a/src/mqtt_socket.c b/src/mqtt_socket.c index e6069382..bb394fdb 100644 --- a/src/mqtt_socket.c +++ b/src/mqtt_socket.c @@ -26,12 +26,18 @@ #ifdef WOLFMQTT_NONBLOCK /* need EWOULDBLOCK and EAGAIN */ - #if defined(MICROCHIP_MPLAB_HARMONY) && \ + #if defined(WOLFMQTT_WOLFIP) + #include "wolfip.h" + #define EWOULDBLOCK WOLFIP_EAGAIN + #define EAGAIN WOLFIP_EAGAIN + #elif defined(MICROCHIP_MPLAB_HARMONY) && \ ((__XC32_VERSION < 4000) || (__XC32_VERSION == 243739000)) /* xc32 versions >= v4.0 no longer have sys/errno.h */ #include + #include + #else + #include #endif - #include #endif #ifdef ENABLE_MQTT_CURL diff --git a/wolfmqtt/mqtt_broker.h b/wolfmqtt/mqtt_broker.h index f22896d8..d19d2dd2 100644 --- a/wolfmqtt/mqtt_broker.h +++ b/wolfmqtt/mqtt_broker.h @@ -327,6 +327,7 @@ typedef struct MqttBroker { const char* tls_ca; /* CA cert for mutual auth (optional) */ byte use_tls; byte tls_version; /* 0=auto (v23), 12=TLS 1.2, 13=TLS 1.3 */ + byte tls_ctx_owned; /* 1 if BrokerTls_Init created tls_ctx */ #endif #ifdef WOLFMQTT_STATIC_MEMORY BrokerClient clients[BROKER_MAX_CLIENTS]; @@ -376,9 +377,20 @@ WOLFMQTT_API int MqttBroker_Stop(MqttBroker* broker); /* Clean up broker resources */ WOLFMQTT_API int MqttBroker_Free(MqttBroker* broker); +/* Start the broker (listen + TLS init). Call once before MqttBroker_Step(). + * For embedded systems that use a cooperative main loop with Step(). */ +WOLFMQTT_API int MqttBroker_Start(MqttBroker* broker); + +/* wolfIP backend initializer. + * wolfIP_stack is a (struct wolfIP*) pointer to the wolfIP stack instance. */ +#ifdef WOLFMQTT_WOLFIP +WOLFMQTT_API int MqttBrokerNet_wolfIP_Init(MqttBrokerNet* net, + void* wolfIP_stack); +#endif + /* Default POSIX backend initializer. * Only available when WOLFMQTT_BROKER_CUSTOM_NET is NOT defined. */ -#ifndef WOLFMQTT_BROKER_CUSTOM_NET +#if !defined(WOLFMQTT_WOLFIP) && !defined(WOLFMQTT_BROKER_CUSTOM_NET) WOLFMQTT_API int MqttBrokerNet_Init(MqttBrokerNet* net); #endif diff --git a/wolfmqtt/mqtt_socket.h b/wolfmqtt/mqtt_socket.h index 3c117efd..0628761e 100644 --- a/wolfmqtt/mqtt_socket.h +++ b/wolfmqtt/mqtt_socket.h @@ -32,6 +32,7 @@ #endif #include "wolfmqtt/mqtt_types.h" + #ifdef ENABLE_MQTT_TLS #ifndef WOLF_TLS_DHKEY_BITS_MIN /* allow define to be overridden */ #ifdef WOLFSSL_MAX_STRENGTH diff --git a/wolfmqtt/mqtt_types.h b/wolfmqtt/mqtt_types.h index bed32a55..f1165d2f 100644 --- a/wolfmqtt/mqtt_types.h +++ b/wolfmqtt/mqtt_types.h @@ -328,7 +328,7 @@ enum MqttPacketResponseCodes { #include #else #undef PRINTF - #define PRINTF + #define PRINTF(...) do { (void)0; } while(0) #endif #endif