LCOV - code coverage report
Current view: top level - app/graph - conn.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 132 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 6 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Marvell.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <arpa/inet.h>
       6                 :            : #include <errno.h>
       7                 :            : #include <netinet/in.h>
       8                 :            : #include <stdio.h>
       9                 :            : #include <stdlib.h>
      10                 :            : #include <string.h>
      11                 :            : #include <sys/epoll.h>
      12                 :            : #include <sys/socket.h>
      13                 :            : #include <sys/types.h>
      14                 :            : #include <unistd.h>
      15                 :            : 
      16                 :            : #include <rte_string_fns.h>
      17                 :            : 
      18                 :            : #include "module_api.h"
      19                 :            : 
      20                 :            : #define MSG_CMD_TOO_LONG "Command too long."
      21                 :            : 
      22                 :            : static int
      23                 :          0 : data_event_handle(struct conn *conn, int fd_client)
      24                 :            : {
      25                 :            :         ssize_t len, i, rc = 0;
      26                 :            : 
      27                 :            :         /* Read input message */
      28                 :          0 :         len = read(fd_client, conn->buf, conn->buf_size);
      29                 :          0 :         if (len == -1) {
      30                 :          0 :                 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
      31                 :            :                         return 0;
      32                 :            : 
      33                 :          0 :                 return -1;
      34                 :            :         }
      35                 :            : 
      36                 :          0 :         if (len == 0)
      37                 :            :                 return rc;
      38                 :            : 
      39                 :            :         /* Handle input messages */
      40                 :          0 :         for (i = 0; i < len; i++) {
      41                 :          0 :                 if (conn->buf[i] == '\n') {
      42                 :            :                         size_t n;
      43                 :            : 
      44                 :          0 :                         conn->msg_in[conn->msg_in_len] = 0;
      45                 :          0 :                         conn->msg_out[0] = 0;
      46                 :            : 
      47                 :          0 :                         conn->msg_handle(conn->msg_in, conn->msg_out, conn->msg_out_len_max,
      48                 :            :                                          conn->msg_handle_arg);
      49                 :            : 
      50                 :          0 :                         n = strlen(conn->msg_out);
      51                 :          0 :                         if (n) {
      52                 :          0 :                                 rc = write(fd_client, conn->msg_out, n);
      53                 :          0 :                                 if (rc == -1)
      54                 :          0 :                                         goto exit;
      55                 :            :                         }
      56                 :            : 
      57                 :          0 :                         conn->msg_in_len = 0;
      58                 :          0 :                 } else if (conn->msg_in_len < conn->msg_in_len_max) {
      59                 :          0 :                         conn->msg_in[conn->msg_in_len] = conn->buf[i];
      60                 :          0 :                         conn->msg_in_len++;
      61                 :            :                 } else {
      62                 :          0 :                         rc = write(fd_client, MSG_CMD_TOO_LONG, strlen(MSG_CMD_TOO_LONG));
      63                 :          0 :                         if (rc == -1)
      64                 :          0 :                                 goto exit;
      65                 :            : 
      66                 :          0 :                         conn->msg_in_len = 0;
      67                 :            :                 }
      68                 :            :         }
      69                 :            : 
      70                 :            :         /* Write prompt */
      71                 :          0 :         rc = write(fd_client, conn->prompt, strlen(conn->prompt));
      72                 :          0 :         rc = (rc == -1) ? -1 : 0;
      73                 :            : 
      74                 :          0 : exit:
      75                 :          0 :         return rc;
      76                 :            : }
      77                 :            : 
      78                 :            : static int
      79                 :          0 : control_event_handle(struct conn *conn, int fd_client)
      80                 :            : {
      81                 :            :         int rc;
      82                 :            : 
      83                 :          0 :         rc = epoll_ctl(conn->fd_client_group, EPOLL_CTL_DEL, fd_client, NULL);
      84                 :          0 :         if (rc == -1)
      85                 :          0 :                 goto exit;
      86                 :            : 
      87                 :          0 :         rc = close(fd_client);
      88                 :          0 :         if (rc == -1)
      89                 :          0 :                 goto exit;
      90                 :            : 
      91                 :            :         rc = 0;
      92                 :            : 
      93                 :          0 : exit:
      94                 :          0 :         return rc;
      95                 :            : }
      96                 :            : 
      97                 :            : struct conn *
      98                 :          0 : conn_init(struct conn_params *p)
      99                 :            : {
     100                 :            :         int fd_server, fd_client_group, rc;
     101                 :            :         struct sockaddr_in server_address;
     102                 :            :         struct conn *conn = NULL;
     103                 :          0 :         int reuse = 1;
     104                 :            : 
     105                 :            :         memset(&server_address, 0, sizeof(server_address));
     106                 :            : 
     107                 :            :         /* Check input arguments */
     108                 :          0 :         if ((p == NULL) || (p->welcome == NULL) || (p->prompt == NULL) || (p->addr == NULL) ||
     109                 :          0 :             (p->buf_size == 0) || (p->msg_in_len_max == 0) || (p->msg_out_len_max == 0) ||
     110                 :          0 :             (p->msg_handle == NULL))
     111                 :          0 :                 goto exit;
     112                 :            : 
     113                 :          0 :         rc = inet_aton(p->addr, &server_address.sin_addr);
     114                 :          0 :         if (rc == 0)
     115                 :          0 :                 goto exit;
     116                 :            : 
     117                 :            :         /* Memory allocation */
     118                 :          0 :         conn = calloc(1, sizeof(struct conn));
     119                 :          0 :         if (conn == NULL)
     120                 :          0 :                 goto exit;
     121                 :            : 
     122                 :          0 :         conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1);
     123                 :          0 :         conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1);
     124                 :          0 :         conn->buf = calloc(1, p->buf_size);
     125                 :          0 :         conn->msg_in = calloc(1, p->msg_in_len_max + 1);
     126                 :          0 :         conn->msg_out = calloc(1, p->msg_out_len_max + 1);
     127                 :            : 
     128                 :          0 :         if ((conn->welcome == NULL) || (conn->prompt == NULL) || (conn->buf == NULL) ||
     129                 :          0 :             (conn->msg_in == NULL) || (conn->msg_out == NULL)) {
     130                 :          0 :                 conn_free(conn);
     131                 :            :                 conn = NULL;
     132                 :          0 :                 goto exit;
     133                 :            :         }
     134                 :            : 
     135                 :            :         /* Server socket */
     136                 :          0 :         server_address.sin_family = AF_INET;
     137                 :          0 :         server_address.sin_port = htons(p->port);
     138                 :            : 
     139                 :          0 :         fd_server = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
     140                 :          0 :         if (fd_server == -1) {
     141                 :          0 :                 conn_free(conn);
     142                 :            :                 conn = NULL;
     143                 :          0 :                 goto exit;
     144                 :            :         }
     145                 :            : 
     146                 :          0 :         if (setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse,
     147                 :            :                        sizeof(reuse)) < 0)
     148                 :          0 :                 goto free;
     149                 :            : 
     150                 :          0 :         rc = bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address));
     151                 :          0 :         if (rc == -1)
     152                 :          0 :                 goto free;
     153                 :            : 
     154                 :          0 :         rc = listen(fd_server, 16);
     155                 :          0 :         if (rc == -1)
     156                 :          0 :                 goto free;
     157                 :            : 
     158                 :            :         /* Client group */
     159                 :          0 :         fd_client_group = epoll_create(1);
     160                 :          0 :         if (fd_client_group == -1)
     161                 :          0 :                 goto free;
     162                 :            : 
     163                 :            :         /* Fill in */
     164                 :          0 :         rte_strscpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX);
     165                 :          0 :         rte_strscpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX);
     166                 :          0 :         conn->buf_size = p->buf_size;
     167                 :          0 :         conn->msg_in_len_max = p->msg_in_len_max;
     168                 :          0 :         conn->msg_out_len_max = p->msg_out_len_max;
     169                 :          0 :         conn->msg_in_len = 0;
     170                 :          0 :         conn->fd_server = fd_server;
     171                 :          0 :         conn->fd_client_group = fd_client_group;
     172                 :          0 :         conn->msg_handle = p->msg_handle;
     173                 :          0 :         conn->msg_handle_arg = p->msg_handle_arg;
     174                 :            : 
     175                 :            : exit:
     176                 :            :         return conn;
     177                 :          0 : free:
     178                 :          0 :         conn_free(conn);
     179                 :          0 :         close(fd_server);
     180                 :            :         conn = NULL;
     181                 :          0 :         return conn;
     182                 :            : }
     183                 :            : 
     184                 :            : void
     185                 :          0 : conn_free(struct conn *conn)
     186                 :            : {
     187                 :          0 :         if (conn == NULL)
     188                 :            :                 return;
     189                 :            : 
     190                 :          0 :         if (conn->fd_client_group)
     191                 :          0 :                 close(conn->fd_client_group);
     192                 :            : 
     193                 :          0 :         if (conn->fd_server)
     194                 :          0 :                 close(conn->fd_server);
     195                 :            : 
     196                 :          0 :         free(conn->msg_out);
     197                 :          0 :         free(conn->msg_in);
     198                 :          0 :         free(conn->prompt);
     199                 :          0 :         free(conn->welcome);
     200                 :          0 :         free(conn);
     201                 :            : }
     202                 :            : 
     203                 :            : int
     204                 :          0 : conn_req_poll(struct conn *conn)
     205                 :            : {
     206                 :            :         struct sockaddr_in client_address;
     207                 :            :         socklen_t client_address_length;
     208                 :            :         struct epoll_event event;
     209                 :            :         int fd_client, rc;
     210                 :            : 
     211                 :            :         /* Check input arguments */
     212                 :          0 :         if (conn == NULL)
     213                 :            :                 return -1;
     214                 :            : 
     215                 :            :         /* Server socket */
     216                 :          0 :         client_address_length = sizeof(client_address);
     217                 :          0 :         fd_client = accept4(conn->fd_server, (struct sockaddr *)&client_address,
     218                 :            :                             &client_address_length, SOCK_NONBLOCK);
     219                 :          0 :         if (fd_client == -1) {
     220                 :          0 :                 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
     221                 :            :                         return 0;
     222                 :            : 
     223                 :          0 :                 return -1;
     224                 :            :         }
     225                 :            : 
     226                 :            :         /* Client group */
     227                 :          0 :         event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
     228                 :          0 :         event.data.fd = fd_client;
     229                 :            : 
     230                 :          0 :         rc = epoll_ctl(conn->fd_client_group, EPOLL_CTL_ADD, fd_client, &event);
     231                 :          0 :         if (rc == -1) {
     232                 :          0 :                 close(fd_client);
     233                 :          0 :                 goto exit;
     234                 :            :         }
     235                 :            : 
     236                 :            :         /* Client */
     237                 :          0 :         rc = write(fd_client, conn->welcome, strlen(conn->welcome));
     238                 :          0 :         if (rc == -1) {
     239                 :          0 :                 close(fd_client);
     240                 :          0 :                 goto exit;
     241                 :            :         }
     242                 :            : 
     243                 :          0 :         rc = write(fd_client, conn->prompt, strlen(conn->prompt));
     244                 :          0 :         if (rc == -1) {
     245                 :          0 :                 close(fd_client);
     246                 :          0 :                 goto exit;
     247                 :            :         }
     248                 :            : 
     249                 :            :         rc = 0;
     250                 :            : 
     251                 :            : exit:
     252                 :            :         return rc;
     253                 :            : }
     254                 :            : 
     255                 :            : int
     256                 :          0 : conn_msg_poll(struct conn *conn)
     257                 :            : {
     258                 :            :         int fd_client, rc, rc_data = 0, rc_control = 0;
     259                 :            :         struct epoll_event event;
     260                 :            : 
     261                 :            :         /* Check input arguments */
     262                 :          0 :         if (conn == NULL)
     263                 :            :                 return -1;
     264                 :            : 
     265                 :            :         /* Client group */
     266                 :          0 :         rc = epoll_wait(conn->fd_client_group, &event, 1, 0);
     267                 :          0 :         if ((rc == -1) || rc == 0)
     268                 :            :                 return rc;
     269                 :            : 
     270                 :          0 :         fd_client = event.data.fd;
     271                 :            : 
     272                 :            :         /* Data available */
     273                 :          0 :         if (event.events & EPOLLIN)
     274                 :          0 :                 rc_data = data_event_handle(conn, fd_client);
     275                 :            : 
     276                 :            :         /* Control events */
     277                 :          0 :         if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP))
     278                 :          0 :                 rc_control = control_event_handle(conn, fd_client);
     279                 :            : 
     280                 :          0 :         if (rc_data || rc_control)
     281                 :          0 :                 return -1;
     282                 :            : 
     283                 :            :         return 0;
     284                 :            : }

Generated by: LCOV version 1.14