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 <tiago.medicci@espressif.com>
This commit is contained in:
Tiago Medicci 2026-06-12 16:15:38 -03:00 committed by Alan C. Assis
parent d6cf3015d8
commit ec764fbbab
5 changed files with 328 additions and 0 deletions

View file

@ -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()

31
examples/lws_echo/Kconfig Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}