LCOV - code coverage report
Current view: top level - zephyr/shell - shell_websocket.h Hit Total Coverage
Test: new.info Lines: 13 31 41.9 %
Date: 2024-12-21 18:13:37

          Line data    Source code
       1           0 : /*
       2             :  * Copyright (c) 2024 Nordic Semiconductor ASA
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             : #ifndef ZEPHYR_INCLUDE_SHELL_WEBSOCKET_H_
       8             : #define ZEPHYR_INCLUDE_SHELL_WEBSOCKET_H_
       9             : 
      10             : #include <zephyr/net/socket.h>
      11             : #include <zephyr/net/http/server.h>
      12             : #include <zephyr/net/http/service.h>
      13             : #include <zephyr/shell/shell.h>
      14             : 
      15             : #ifdef __cplusplus
      16             : extern "C" {
      17             : #endif
      18             : 
      19           0 : #define SHELL_WEBSOCKET_SERVICE_COUNT CONFIG_SHELL_WEBSOCKET_BACKEND_COUNT
      20             : 
      21             : /** Line buffer structure. */
      22           1 : struct shell_websocket_line_buf {
      23             :         /** Line buffer. */
      24           1 :         char buf[CONFIG_SHELL_WEBSOCKET_LINE_BUF_SIZE];
      25             : 
      26             :         /** Current line length. */
      27           1 :         uint16_t len;
      28             : };
      29             : 
      30             : /** WEBSOCKET-based shell transport. */
      31           1 : struct shell_websocket {
      32             :         /** Handler function registered by shell. */
      33           1 :         shell_transport_handler_t shell_handler;
      34             : 
      35             :         /** Context registered by shell. */
      36           1 :         void *shell_context;
      37             : 
      38             :         /** Buffer for outgoing line. */
      39           1 :         struct shell_websocket_line_buf line_out;
      40             : 
      41             :         /** Array for sockets used by the websocket service. */
      42           1 :         struct zsock_pollfd fds[1];
      43             : 
      44             :         /** Input buffer. */
      45           1 :         uint8_t rx_buf[CONFIG_SHELL_CMD_BUFF_SIZE];
      46             : 
      47             :         /** Number of data bytes within the input buffer. */
      48           1 :         size_t rx_len;
      49             : 
      50             :         /** Mutex protecting the input buffer access. */
      51           1 :         struct k_mutex rx_lock;
      52             : 
      53             :         /** The delayed work is used to send non-lf terminated output that has
      54             :          *  been around for "too long". This will prove to be useful
      55             :          *  to send the shell prompt for instance.
      56             :          */
      57           1 :         struct k_work_delayable send_work;
      58           0 :         struct k_work_sync work_sync;
      59             : 
      60             :         /** If set, no output is sent to the WEBSOCKET client. */
      61           1 :         bool output_lock;
      62             : };
      63             : 
      64           0 : extern const struct shell_transport_api shell_websocket_transport_api;
      65           0 : extern int shell_websocket_setup(int ws_socket, void *user_data);
      66           0 : extern int shell_websocket_enable(const struct shell *sh);
      67             : 
      68           0 : #define GET_WS_NAME(_service) ws_ctx_##_service
      69           0 : #define GET_WS_SHELL_NAME(_name) shell_websocket_##_name
      70           0 : #define GET_WS_TRANSPORT_NAME(_service) transport_shell_ws_##_service
      71           0 : #define GET_WS_DETAIL_NAME(_service) ws_res_detail_##_service
      72             : 
      73           0 : #define SHELL_WEBSOCKET_DEFINE(_service)                                        \
      74             :         static struct shell_websocket GET_WS_NAME(_service);                    \
      75             :         static struct shell_transport GET_WS_TRANSPORT_NAME(_service) = {       \
      76             :                 .api = &shell_websocket_transport_api,                              \
      77             :                 .ctx = &GET_WS_NAME(_service),                                      \
      78             :         }
      79             : 
      80           0 : #define SHELL_WS_PORT_NAME(_service)    http_service_##_service
      81           0 : #define SHELL_WS_BUF_NAME(_service)     ws_recv_buffer_##_service
      82           0 : #define SHELL_WS_TEMP_RECV_BUF_SIZE 256
      83             : 
      84           0 : #define DEFINE_WEBSOCKET_HTTP_SERVICE(_service)                                 \
      85             :         uint8_t SHELL_WS_BUF_NAME(_service)[SHELL_WS_TEMP_RECV_BUF_SIZE];       \
      86             :         struct http_resource_detail_websocket                                   \
      87             :             GET_WS_DETAIL_NAME(_service) = {                                    \
      88             :                 .common = {                                                     \
      89             :                         .type = HTTP_RESOURCE_TYPE_WEBSOCKET,                   \
      90             :                                                                                 \
      91             :                         /* We need HTTP/1.1 GET method for upgrading */         \
      92             :                         .bitmask_of_supported_http_methods = BIT(HTTP_GET),     \
      93             :                 },                                                              \
      94             :                 .cb = shell_websocket_setup,                                    \
      95             :                 .data_buffer = SHELL_WS_BUF_NAME(_service),                     \
      96             :                 .data_buffer_len = sizeof(SHELL_WS_BUF_NAME(_service)),         \
      97             :                 .user_data = &GET_WS_NAME(_service),                                \
      98             :         };                                                                      \
      99             :         HTTP_RESOURCE_DEFINE(ws_resource_##_service, _service,                  \
     100             :                              "/" CONFIG_SHELL_WEBSOCKET_ENDPOINT_URL,         \
     101             :                              &GET_WS_DETAIL_NAME(_service))
     102             : 
     103           0 : #define DEFINE_WEBSOCKET_SERVICE(_service)                                      \
     104             :         SHELL_WEBSOCKET_DEFINE(_service);                                       \
     105             :         SHELL_DEFINE(shell_websocket_##_service,                                \
     106             :                      CONFIG_SHELL_WEBSOCKET_PROMPT,                             \
     107             :                      &GET_WS_TRANSPORT_NAME(_service),                              \
     108             :                      CONFIG_SHELL_WEBSOCKET_LOG_MESSAGE_QUEUE_SIZE,             \
     109             :                      CONFIG_SHELL_WEBSOCKET_LOG_MESSAGE_QUEUE_TIMEOUT,          \
     110             :                      SHELL_FLAG_OLF_CRLF);                                      \
     111             :         DEFINE_WEBSOCKET_HTTP_SERVICE(_service)
     112             : 
     113             : #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
     114             : /* Use a secure connection only for Websocket. */
     115             : #define WEBSOCKET_CONSOLE_DEFINE(_service, _sec_tag_list, _sec_tag_list_size) \
     116             :         static uint16_t SHELL_WS_PORT_NAME(_service) =                    \
     117             :                 CONFIG_SHELL_WEBSOCKET_PORT;                              \
     118             :         HTTPS_SERVICE_DEFINE(_service,                                    \
     119             :                              CONFIG_SHELL_WEBSOCKET_IP_ADDR,              \
     120             :                              &SHELL_WS_PORT_NAME(_service),           \
     121             :                              SHELL_WEBSOCKET_SERVICE_COUNT,               \
     122             :                              SHELL_WEBSOCKET_SERVICE_COUNT,               \
     123             :                              NULL,                                        \
     124             :                              _sec_tag_list,                               \
     125             :                              _sec_tag_list_size);                         \
     126             :         DEFINE_WEBSOCKET_SERVICE(_service);                               \
     127             : 
     128             : 
     129             : #else /* CONFIG_NET_SOCKETS_SOCKOPT_TLS */
     130             : /* TLS not possible so define only normal HTTP service */
     131           0 : #define WEBSOCKET_CONSOLE_DEFINE(_service, _sec_tag_list, _sec_tag_list_size) \
     132             :         static uint16_t SHELL_WS_PORT_NAME(_service) =                  \
     133             :                 CONFIG_SHELL_WEBSOCKET_PORT;                            \
     134             :         HTTP_SERVICE_DEFINE(_service,                                   \
     135             :                             CONFIG_SHELL_WEBSOCKET_IP_ADDR,             \
     136             :                             &SHELL_WS_PORT_NAME(_service),          \
     137             :                             SHELL_WEBSOCKET_SERVICE_COUNT,              \
     138             :                             SHELL_WEBSOCKET_SERVICE_COUNT,              \
     139             :                             NULL);                                      \
     140             :         DEFINE_WEBSOCKET_SERVICE(_service)
     141             : 
     142             : #endif /* CONFIG_NET_SOCKETS_SOCKOPT_TLS */
     143             : 
     144           0 : #define WEBSOCKET_CONSOLE_ENABLE(_service)                              \
     145             :         (void)shell_websocket_enable(&GET_WS_SHELL_NAME(_service))
     146             : 
     147             : #ifdef __cplusplus
     148             : }
     149             : #endif
     150             : 
     151             : #endif /* ZEPHYR_INCLUDE_SHELL_WEBSOCKET_H_ */

Generated by: LCOV version 1.14