This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit ec764fbbab6afd61e05d2171c0d258853f324194 Author: Tiago Medicci <[email protected]> AuthorDate: Fri Jun 12 16:15:38 2026 -0300 examples/lws_echo: Add a simple websocket server example This commit adds a simple websocket server example that echoes data back to the client using libwebsockets. Signed-off-by: Tiago Medicci <[email protected]> --- examples/lws_echo/CMakeLists.txt | 37 +++++++ examples/lws_echo/Kconfig | 31 ++++++ examples/lws_echo/Make.defs | 25 +++++ examples/lws_echo/Makefile | 32 ++++++ examples/lws_echo/lws_echo_main.c | 203 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 328 insertions(+) diff --git a/examples/lws_echo/CMakeLists.txt b/examples/lws_echo/CMakeLists.txt new file mode 100644 index 000000000..d959489f6 --- /dev/null +++ b/examples/lws_echo/CMakeLists.txt @@ -0,0 +1,37 @@ +# ############################################################################## +# apps/examples/lws_echo/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_EXAMPLES_LWS_ECHO) + nuttx_add_application( + NAME + ${CONFIG_EXAMPLES_LWS_ECHO_PROGNAME} + PRIORITY + ${CONFIG_EXAMPLES_LWS_ECHO_PRIORITY} + STACKSIZE + ${CONFIG_EXAMPLES_LWS_ECHO_STACKSIZE} + MODULE + ${CONFIG_EXAMPLES_LWS_ECHO} + DEPENDS + libwebsockets + SRCS + lws_echo_main.c) +endif() diff --git a/examples/lws_echo/Kconfig b/examples/lws_echo/Kconfig new file mode 100644 index 000000000..b58daa24e --- /dev/null +++ b/examples/lws_echo/Kconfig @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_LWS_ECHO + tristate "libwebsockets WebSocket echo server" + default n + depends on NETUTILS_LIBWEBSOCKETS && NETUTILS_LIBWEBSOCKETS_SERVER + ---help--- + Simple WebSocket echo server using libwebsockets without TLS. + +if EXAMPLES_LWS_ECHO + +config EXAMPLES_LWS_ECHO_PROGNAME + string "Program name" + default "lws_echo" + +config EXAMPLES_LWS_ECHO_PRIORITY + int "Task priority" + default 100 + +config EXAMPLES_LWS_ECHO_STACKSIZE + int "Stack size" + default 16384 + +config EXAMPLES_LWS_ECHO_PORT + int "WebSocket server TCP port" + default 9000 + +endif diff --git a/examples/lws_echo/Make.defs b/examples/lws_echo/Make.defs new file mode 100644 index 000000000..b0a46ccd5 --- /dev/null +++ b/examples/lws_echo/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/examples/lws_echo/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_LWS_ECHO),) +CONFIGURED_APPS += $(APPDIR)/examples/lws_echo +endif diff --git a/examples/lws_echo/Makefile b/examples/lws_echo/Makefile new file mode 100644 index 000000000..48da93216 --- /dev/null +++ b/examples/lws_echo/Makefile @@ -0,0 +1,32 @@ +############################################################################ +# apps/examples/lws_echo/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = $(CONFIG_EXAMPLES_LWS_ECHO_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_LWS_ECHO_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_LWS_ECHO_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_LWS_ECHO) + +MAINSRC = lws_echo_main.c + +include $(APPDIR)/Application.mk diff --git a/examples/lws_echo/lws_echo_main.c b/examples/lws_echo/lws_echo_main.c new file mode 100644 index 000000000..48bf644f0 --- /dev/null +++ b/examples/lws_echo/lws_echo_main.c @@ -0,0 +1,203 @@ +/**************************************************************************** + * apps/examples/lws_echo/lws_echo_main.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <libwebsockets.h> +#include <stdio.h> +#include <string.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_EXAMPLES_LWS_ECHO_PORT +# define CONFIG_EXAMPLES_LWS_ECHO_PORT 9000 +#endif + +#define LWS_ECHO_IOBUF_SIZE 256 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct lws_echo_session_s +{ + unsigned char buf[LWS_PRE + LWS_ECHO_IOBUF_SIZE]; + size_t len; + int pending; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int callback_echo(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct lws_protocols g_protocols[] = +{ + { + "echo-protocol", + callback_echo, + sizeof(struct lws_echo_session_s), + LWS_ECHO_IOBUF_SIZE, + 0, NULL, 0 + }, + LWS_PROTOCOL_LIST_TERM +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: callback_echo + * + * Description: + * libwebsockets protocol callback for the echo server. + * + * Input Parameters: + * wsi - Websocket instance. + * reason - Callback reason. + * user - Per-session data. + * in - Received data. + * len - Length of received data. + * + * Returned Value: + * Zero on success; non-zero on failure. + * + ****************************************************************************/ + +static int callback_echo(struct lws *wsi, + enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + struct lws_echo_session_s *pss = (struct lws_echo_session_s *)user; + + switch (reason) + { + case LWS_CALLBACK_ESTABLISHED: + printf("lws_echo: client connected\n"); + pss->pending = 0; + break; + + case LWS_CALLBACK_RECEIVE: + if (len > sizeof(pss->buf) - LWS_PRE) + { + len = sizeof(pss->buf) - LWS_PRE; + } + + memcpy(&pss->buf[LWS_PRE], in, len); + pss->len = len; + pss->pending = 1; + lws_callback_on_writable(wsi); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + if (!pss->pending) + { + break; + } + + lws_write(wsi, &pss->buf[LWS_PRE], pss->len, LWS_WRITE_TEXT); + pss->pending = 0; + break; + + case LWS_CALLBACK_CLOSED: + printf("lws_echo: client disconnected\n"); + break; + + default: + break; + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + * + * Description: + * Start a libwebsockets WebSocket echo server. + * + * Input Parameters: + * Standard argc and argv. + * + * Returned Value: + * Zero on success; non-zero on failure. + * + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + struct lws_context_creation_info info; + struct lws_context *context; + int n; + + lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE, NULL); + + printf("lws_echo: starting WebSocket echo server on port %d\n", + CONFIG_EXAMPLES_LWS_ECHO_PORT); + printf("lws_echo: connect with ws://<device-ip>:%d " + "(subprotocol echo-protocol)\n", + CONFIG_EXAMPLES_LWS_ECHO_PORT); + + memset(&info, 0, sizeof(info)); + info.port = CONFIG_EXAMPLES_LWS_ECHO_PORT; + info.protocols = g_protocols; + info.vhost_name = "localhost"; + info.options = 0; + + context = lws_create_context(&info); + if (context == NULL) + { + printf("lws_echo: ERROR creating context\n"); + return 1; + } + + printf("lws_echo: server running\n"); + + n = 0; + while (n >= 0) + { + n = lws_service(context, 100); + } + + lws_context_destroy(context); + printf("lws_echo: server stopped\n"); + + return 0; +}
