LCOV - code coverage report
Current view: top level - plugins/hs_apps/vcl - sock_test_client.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 192 518 37.1 %
Date: 2023-07-05 22:20:52 Functions: 5 14 35.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017-2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : 
      16             : #include <unistd.h>
      17             : #include <errno.h>
      18             : #include <stdlib.h>
      19             : #include <ctype.h>
      20             : #include <sys/types.h>
      21             : #include <sys/socket.h>
      22             : #include <stdio.h>
      23             : #include <time.h>
      24             : #include <arpa/inet.h>
      25             : #include <hs_apps/vcl/sock_test.h>
      26             : #include <fcntl.h>
      27             : #include <sys/un.h>
      28             : 
      29             : typedef struct
      30             : {
      31             :   int af_unix_echo_tx;
      32             :   int af_unix_echo_rx;
      33             :   struct sockaddr_storage server_addr;
      34             :   uint32_t server_addr_size;
      35             :   uint32_t cfg_seq_num;
      36             :   vcl_test_session_t ctrl_socket;
      37             :   vcl_test_session_t *test_socket;
      38             :   uint32_t num_test_sockets;
      39             :   uint8_t dump_cfg;
      40             : } sock_client_main_t;
      41             : 
      42             : sock_client_main_t sock_client_main;
      43             : 
      44             : static int
      45          20 : sock_test_cfg_sync (vcl_test_session_t * socket)
      46             : {
      47          20 :   sock_client_main_t *scm = &sock_client_main;
      48          20 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
      49          20 :   vcl_test_cfg_t *rl_cfg = (vcl_test_cfg_t *) socket->rxbuf;
      50             :   int rx_bytes, tx_bytes;
      51             : 
      52          20 :   if (socket->cfg.verbose)
      53           0 :     vcl_test_cfg_dump (&socket->cfg, 1 /* is_client */ );
      54             : 
      55          20 :   ctrl->cfg.seq_num = ++scm->cfg_seq_num;
      56          20 :   if (socket->cfg.verbose)
      57             :     {
      58           0 :       stinf ("(fd %d): Sending config sent to server.\n", socket->fd);
      59           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
      60             :     }
      61          20 :   tx_bytes = sock_test_write (socket->fd, (uint8_t *) & ctrl->cfg,
      62             :                               sizeof (ctrl->cfg), NULL, ctrl->cfg.verbose);
      63          20 :   if (tx_bytes < 0)
      64           0 :     stabrt ("(fd %d): write test cfg failed (%d)!", socket->fd, tx_bytes);
      65             : 
      66          20 :   rx_bytes = sock_test_read (socket->fd, (uint8_t *) socket->rxbuf,
      67             :                              sizeof (vcl_test_cfg_t), NULL);
      68          20 :   if (rx_bytes < 0)
      69           0 :     return rx_bytes;
      70             : 
      71          20 :   if (rl_cfg->magic != VCL_TEST_CFG_CTRL_MAGIC)
      72           0 :     stabrt ("(fd %d): Bad server reply cfg -- aborting!\n", socket->fd);
      73             : 
      74          20 :   if ((rx_bytes != sizeof (vcl_test_cfg_t))
      75          20 :       || !vcl_test_cfg_verify (rl_cfg, &ctrl->cfg))
      76           0 :     stabrt ("(fd %d): Invalid config received from server!\n", socket->fd);
      77             : 
      78          20 :   if (socket->cfg.verbose)
      79             :     {
      80           0 :       stinf ("(fd %d): Got config back from server.", socket->fd);
      81           0 :       vcl_test_cfg_dump (rl_cfg, 1 /* is_client */ );
      82             :     }
      83          40 :   ctrl->cfg.ctrl_handle = ((ctrl->cfg.ctrl_handle == ~0) ?
      84          20 :                            rl_cfg->ctrl_handle : ctrl->cfg.ctrl_handle);
      85             : 
      86          20 :   return 0;
      87             : }
      88             : 
      89             : static void
      90           0 : sock_client_echo_af_unix (sock_client_main_t * scm)
      91             : {
      92             :   int fd, rv;
      93             :   struct sockaddr_un serveraddr;
      94             :   uint8_t buffer[256];
      95           0 :   size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1;
      96             :   struct timeval timeout;
      97             : 
      98             :   /* Open AF_UNIX socket and send an echo to test mixed epoll on server.
      99             :    */
     100           0 :   fd = socket (AF_UNIX, SOCK_STREAM, 0);
     101           0 :   if (fd < 0)
     102           0 :     stfail ("socket()");
     103             : 
     104           0 :   memset (&serveraddr, 0, sizeof (serveraddr));
     105           0 :   serveraddr.sun_family = AF_UNIX;
     106           0 :   strncpy (serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME,
     107             :            sizeof (serveraddr.sun_path));
     108           0 :   rv = connect (fd, (struct sockaddr *) &serveraddr, SUN_LEN (&serveraddr));
     109           0 :   if (rv < 0)
     110           0 :     stfail ("connect()");
     111             : 
     112           0 :   scm->af_unix_echo_tx++;
     113           0 :   strncpy ((char *) buffer, SOCK_TEST_MIXED_EPOLL_DATA, sizeof (buffer));
     114           0 :   timeout.tv_sec = 0;
     115           0 :   timeout.tv_usec = 250000;
     116           0 :   select (0, NULL, NULL, NULL, &timeout);   /* delay .25 secs */
     117           0 :   rv = write (fd, buffer, nbytes);
     118           0 :   if (rv < 0)
     119           0 :     stfail ("write()");
     120             : 
     121           0 :   if (rv < nbytes)
     122           0 :     stabrt ("write(fd %d, \"%s\", %lu) returned %d!", fd, buffer, nbytes, rv);
     123             : 
     124           0 :   stinf ("(AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
     125           0 :   memset (buffer, 0, sizeof (buffer));
     126           0 :   rv = read (fd, buffer, nbytes);
     127           0 :   if (rv < 0)
     128           0 :     stfail ("read()");
     129             : 
     130           0 :   if (rv < nbytes)
     131           0 :     stabrt ("read(fd %d, %p, %lu) returned %d!\n", fd, buffer, nbytes, rv);
     132             : 
     133           0 :   if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes))
     134             :     {
     135           0 :       stinf ("(AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
     136           0 :       scm->af_unix_echo_rx++;
     137             :     }
     138             :   else
     139           0 :     stabrt ("(AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
     140             : 
     141           0 :   close (fd);
     142           0 : }
     143             : 
     144             : static void
     145           0 : echo_test_client (void)
     146             : {
     147           0 :   sock_client_main_t *scm = &sock_client_main;
     148           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     149             :   vcl_test_session_t *tsock;
     150             :   int rx_bytes, tx_bytes, nbytes;
     151             :   uint32_t i, n;
     152             :   int rv;
     153           0 :   int nfds = 0;
     154             :   fd_set wr_fdset, rd_fdset;
     155           0 :   fd_set _wfdset, *wfdset = &_wfdset;
     156           0 :   fd_set _rfdset, *rfdset = &_rfdset;
     157             : 
     158           0 :   FD_ZERO (&wr_fdset);
     159           0 :   FD_ZERO (&rd_fdset);
     160           0 :   memset (&ctrl->stats, 0, sizeof (ctrl->stats));
     161           0 :   ctrl->cfg.total_bytes = nbytes = strlen (ctrl->txbuf) + 1;
     162           0 :   for (n = 0; n != ctrl->cfg.num_test_sessions; n++)
     163             :     {
     164           0 :       tsock = &scm->test_socket[n];
     165           0 :       tsock->cfg = ctrl->cfg;
     166           0 :       vcl_test_session_buf_alloc (tsock);
     167           0 :       if (sock_test_cfg_sync (tsock))
     168           0 :         return;
     169             : 
     170           0 :       memcpy (tsock->txbuf, ctrl->txbuf, nbytes);
     171           0 :       memset (&tsock->stats, 0, sizeof (tsock->stats));
     172             : 
     173           0 :       FD_SET (tsock->fd, &wr_fdset);
     174           0 :       FD_SET (tsock->fd, &rd_fdset);
     175           0 :       nfds = ((tsock->fd + 1) > nfds) ? (tsock->fd + 1) : nfds;
     176             :     }
     177             : 
     178           0 :   nfds++;
     179           0 :   clock_gettime (CLOCK_REALTIME, &ctrl->stats.start);
     180           0 :   while (n)
     181             :     {
     182           0 :       _wfdset = wr_fdset;
     183           0 :       _rfdset = rd_fdset;
     184             : 
     185             :       struct timeval timeout;
     186           0 :       timeout.tv_sec = 0;
     187           0 :       timeout.tv_usec = 0;
     188           0 :       rv = select (nfds, rfdset, wfdset, NULL, &timeout);
     189             : 
     190           0 :       if (rv < 0)
     191           0 :         stfail ("select()");
     192             : 
     193           0 :       if (rv == 0)
     194           0 :         continue;
     195             : 
     196           0 :       for (i = 0; i < ctrl->cfg.num_test_sessions; i++)
     197             :         {
     198           0 :           tsock = &scm->test_socket[i];
     199           0 :           if (!((tsock->stats.stop.tv_sec == 0) &&
     200           0 :                 (tsock->stats.stop.tv_nsec == 0)))
     201           0 :             continue;
     202             : 
     203           0 :           if (FD_ISSET (tsock->fd, wfdset) &&
     204           0 :               (tsock->stats.tx_bytes < ctrl->cfg.total_bytes))
     205             :             {
     206           0 :               tx_bytes = sock_test_write (tsock->fd, (uint8_t *) tsock->txbuf,
     207             :                                           nbytes, &tsock->stats,
     208             :                                           ctrl->cfg.verbose);
     209           0 :               if (tx_bytes < 0)
     210           0 :                 stabrt ("sock_test_write(%d) failed -- aborting test!",
     211             :                         tsock->fd);
     212             : 
     213           0 :               stinf ("(fd %d): TX (%d bytes) - '%s'", tsock->fd, tx_bytes,
     214             :                      tsock->txbuf);
     215             :             }
     216             : 
     217           0 :           if ((FD_ISSET (tsock->fd, rfdset)) &&
     218           0 :               (tsock->stats.rx_bytes < ctrl->cfg.total_bytes))
     219             :             {
     220           0 :               rx_bytes = sock_test_read (tsock->fd, (uint8_t *) tsock->rxbuf,
     221             :                                          nbytes, &tsock->stats);
     222           0 :               if (rx_bytes > 0)
     223             :                 {
     224           0 :                   stinf ("(fd %d): RX (%d bytes)\n", tsock->fd, rx_bytes);
     225             : 
     226           0 :                   if (tsock->stats.rx_bytes != tsock->stats.tx_bytes)
     227           0 :                     stinf ("bytes read (%lu) != bytes written (%lu)!\n",
     228             :                            tsock->stats.rx_bytes, tsock->stats.tx_bytes);
     229             :                 }
     230             :             }
     231             : 
     232           0 :           if (tsock->stats.rx_bytes >= ctrl->cfg.total_bytes)
     233             :             {
     234           0 :               clock_gettime (CLOCK_REALTIME, &tsock->stats.stop);
     235           0 :               n--;
     236             :             }
     237             :         }
     238             :     }
     239           0 :   clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop);
     240             : 
     241           0 :   sock_client_echo_af_unix (scm);
     242             : 
     243           0 :   for (i = 0; i < ctrl->cfg.num_test_sessions; i++)
     244             :     {
     245           0 :       tsock = &scm->test_socket[i];
     246           0 :       tsock->stats.start = ctrl->stats.start;
     247             : 
     248           0 :       if (ctrl->cfg.verbose)
     249             :         {
     250             :           static char buf[64];
     251             : 
     252           0 :           snprintf (buf, sizeof (buf), "CLIENT (fd %d) RESULTS", tsock->fd);
     253           0 :           vcl_test_stats_dump (buf, &tsock->stats,
     254             :                                1 /* show_rx */ , 1 /* show tx */ ,
     255           0 :                                ctrl->cfg.verbose);
     256             :         }
     257             : 
     258           0 :       vcl_test_stats_accumulate (&ctrl->stats, &tsock->stats);
     259             :     }
     260             : 
     261           0 :   if (ctrl->cfg.verbose)
     262             :     {
     263           0 :       vcl_test_stats_dump ("CLIENT RESULTS", &ctrl->stats,
     264             :                            1 /* show_rx */ , 1 /* show tx */ ,
     265           0 :                            ctrl->cfg.verbose);
     266           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     267             : 
     268           0 :       if (ctrl->cfg.verbose > 1)
     269             :         {
     270           0 :           stinf ("  ctrl socket info\n"
     271             :                  VCL_TEST_SEPARATOR_STRING
     272             :                  "          fd:  %d (0x%08x)\n"
     273             :                  "       rxbuf:  %p\n"
     274             :                  "  rxbuf size:  %u (0x%08x)\n"
     275             :                  "       txbuf:  %p\n"
     276             :                  "  txbuf size:  %u (0x%08x)\n"
     277             :                  VCL_TEST_SEPARATOR_STRING,
     278             :                  ctrl->fd, (uint32_t) ctrl->fd,
     279             :                  ctrl->rxbuf, ctrl->rxbuf_size, ctrl->rxbuf_size,
     280             :                  ctrl->txbuf, ctrl->txbuf_size, ctrl->txbuf_size);
     281             :         }
     282             :     }
     283             : }
     284             : 
     285             : static void
     286           2 : stream_test_client (vcl_test_t test)
     287             : {
     288           2 :   sock_client_main_t *scm = &sock_client_main;
     289           2 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     290             :   vcl_test_session_t *tsock;
     291           2 :   int tx_bytes, rv, nfds = 0;;
     292             :   uint32_t i, n;
     293             :   fd_set wr_fdset, rd_fdset;
     294           2 :   fd_set _wfdset, *wfdset = &_wfdset;
     295           2 :   fd_set _rfdset, *rfdset = (test == VCL_TEST_TYPE_BI) ? &_rfdset : 0;
     296             : 
     297           2 :   ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
     298           2 :   ctrl->cfg.ctrl_handle = ~0;
     299             : 
     300           2 :   stinf ("\n" SOCK_TEST_BANNER_STRING
     301             :          "CLIENT (fd %d): %s-directional Stream Test!\n\n"
     302             :          "CLIENT (fd %d): Sending config to server on ctrl socket...\n",
     303             :          ctrl->fd, test == VCL_TEST_TYPE_BI ? "Bi" : "Uni", ctrl->fd);
     304             : 
     305           2 :   if (sock_test_cfg_sync (ctrl))
     306           0 :     stabrt ("test cfg sync failed -- aborting!");
     307             : 
     308           2 :   FD_ZERO (&wr_fdset);
     309           2 :   FD_ZERO (&rd_fdset);
     310           2 :   memset (&ctrl->stats, 0, sizeof (ctrl->stats));
     311           8 :   for (n = 0; n != ctrl->cfg.num_test_sessions; n++)
     312             :     {
     313           6 :       tsock = &scm->test_socket[n];
     314           6 :       tsock->cfg = ctrl->cfg;
     315           6 :       vcl_test_session_buf_alloc (tsock);
     316           6 :       stinf ("(fd %d): Sending config to server on test socket %d...\n",
     317             :              tsock->fd, n);
     318           6 :       sock_test_cfg_sync (tsock);
     319             : 
     320             :       /* Fill payload with incrementing uint32's */
     321       49158 :       for (i = 0; i < tsock->txbuf_size; i++)
     322       49152 :         tsock->txbuf[i] = i & 0xff;
     323             : 
     324           6 :       memset (&tsock->stats, 0, sizeof (tsock->stats));
     325           6 :       FD_SET (tsock->fd, &wr_fdset);
     326           6 :       FD_SET (tsock->fd, &rd_fdset);
     327           6 :       nfds = ((tsock->fd + 1) > nfds) ? (tsock->fd + 1) : nfds;
     328             :     }
     329             : 
     330           2 :   nfds++;
     331           2 :   clock_gettime (CLOCK_REALTIME, &ctrl->stats.start);
     332        4381 :   while (n)
     333             :     {
     334        4379 :       _wfdset = wr_fdset;
     335        4379 :       _rfdset = rd_fdset;
     336             : 
     337             :       struct timeval timeout;
     338        4379 :       timeout.tv_sec = 0;
     339        4379 :       timeout.tv_usec = 0;
     340        4379 :       rv = select (nfds, rfdset, wfdset, NULL, &timeout);
     341             : 
     342        4379 :       if (rv < 0)
     343           0 :         stfail ("select()");
     344             : 
     345        4379 :       if (rv == 0)
     346          98 :         continue;
     347             : 
     348       12562 :       for (i = 0; i < ctrl->cfg.num_test_sessions; i++)
     349             :         {
     350        8281 :           tsock = &scm->test_socket[i];
     351        8281 :           if (!((tsock->stats.stop.tv_sec == 0) &&
     352        8281 :                 (tsock->stats.stop.tv_nsec == 0)))
     353           0 :             continue;
     354             : 
     355        8281 :           if ((test == VCL_TEST_TYPE_BI) &&
     356        3281 :               FD_ISSET (tsock->fd, rfdset) &&
     357         312 :               (tsock->stats.rx_bytes < ctrl->cfg.total_bytes))
     358             :             {
     359         312 :               (void) sock_test_read (tsock->fd,
     360         312 :                                      (uint8_t *) tsock->rxbuf,
     361             :                                      tsock->rxbuf_size, &tsock->stats);
     362             :             }
     363             : 
     364        8281 :           if (FD_ISSET (tsock->fd, wfdset) &&
     365        8271 :               (tsock->stats.tx_bytes < ctrl->cfg.total_bytes))
     366             :             {
     367        6000 :               tx_bytes = sock_test_write (tsock->fd, (uint8_t *) tsock->txbuf,
     368        6000 :                                           ctrl->cfg.txbuf_size, &tsock->stats,
     369             :                                           ctrl->cfg.verbose);
     370        6000 :               if (tx_bytes < 0)
     371           0 :                 stabrt ("sock_test_write(%d) failed -- aborting test!",
     372             :                         tsock->fd);
     373             :             }
     374             : 
     375        8281 :           if (((test == VCL_TEST_TYPE_UNI) &&
     376        8281 :                (tsock->stats.tx_bytes >= ctrl->cfg.total_bytes)) ||
     377        3281 :               ((test == VCL_TEST_TYPE_BI) &&
     378        3281 :                (tsock->stats.rx_bytes >= ctrl->cfg.total_bytes)))
     379             :             {
     380           6 :               clock_gettime (CLOCK_REALTIME, &tsock->stats.stop);
     381           6 :               n--;
     382             :             }
     383             :         }
     384             :     }
     385           2 :   clock_gettime (CLOCK_REALTIME, &ctrl->stats.stop);
     386             : 
     387           2 :   stinf ("(fd %d): Sending config to server on ctrl socket...\n", ctrl->fd);
     388             : 
     389           2 :   if (sock_test_cfg_sync (ctrl))
     390           0 :     stabrt ("test cfg sync failed -- aborting!");
     391             : 
     392           8 :   for (i = 0; i < ctrl->cfg.num_test_sessions; i++)
     393             :     {
     394           6 :       tsock = &scm->test_socket[i];
     395             : 
     396           6 :       if (ctrl->cfg.verbose)
     397             :         {
     398             :           static char buf[64];
     399             : 
     400           0 :           snprintf (buf, sizeof (buf), "CLIENT (fd %d) RESULTS", tsock->fd);
     401           0 :           vcl_test_stats_dump (buf, &tsock->stats,
     402             :                                test == VCL_TEST_TYPE_BI /* show_rx */ ,
     403           0 :                                1 /* show tx */ , ctrl->cfg.verbose);
     404             :         }
     405             : 
     406           6 :       vcl_test_stats_accumulate (&ctrl->stats, &tsock->stats);
     407             :     }
     408             : 
     409           2 :   vcl_test_stats_dump ("CLIENT RESULTS", &ctrl->stats,
     410             :                        test == VCL_TEST_TYPE_BI /* show_rx */ ,
     411           2 :                        1 /* show tx */ , ctrl->cfg.verbose);
     412           2 :   vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     413             : 
     414           2 :   if (ctrl->cfg.verbose)
     415             :     {
     416           0 :       stinf ("  ctrl socket info\n"
     417             :              VCL_TEST_SEPARATOR_STRING
     418             :              "          fd:  %d (0x%08x)\n"
     419             :              "       rxbuf:  %p\n"
     420             :              "  rxbuf size:  %u (0x%08x)\n"
     421             :              "       txbuf:  %p\n"
     422             :              "  txbuf size:  %u (0x%08x)\n"
     423             :              VCL_TEST_SEPARATOR_STRING,
     424             :              ctrl->fd, (uint32_t) ctrl->fd,
     425             :              ctrl->rxbuf, ctrl->rxbuf_size, ctrl->rxbuf_size,
     426             :              ctrl->txbuf, ctrl->txbuf_size, ctrl->txbuf_size);
     427             :     }
     428             : 
     429           2 :   ctrl->cfg.test = VCL_TEST_TYPE_ECHO;
     430           2 :   if (sock_test_cfg_sync (ctrl))
     431           0 :     stabrt ("post-test cfg sync failed!");
     432             : 
     433           2 :   stinf ("(fd %d): %s-directional Stream Test Complete!\n"
     434             :          SOCK_TEST_BANNER_STRING "\n", ctrl->fd,
     435             :          test == VCL_TEST_TYPE_BI ? "Bi" : "Uni");
     436           2 : }
     437             : 
     438             : static void
     439           2 : exit_client (void)
     440             : {
     441           2 :   sock_client_main_t *scm = &sock_client_main;
     442           2 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     443             :   vcl_test_session_t *tsock;
     444             :   int i;
     445             : 
     446           2 :   stinf ("af_unix_echo_tx %d, af_unix_echo_rx %d\n",
     447             :          scm->af_unix_echo_tx, scm->af_unix_echo_rx);
     448           8 :   for (i = 0; i < ctrl->cfg.num_test_sessions; i++)
     449             :     {
     450           6 :       tsock = &scm->test_socket[i];
     451           6 :       tsock->cfg.test = VCL_TEST_TYPE_EXIT;
     452             : 
     453             :       /* coverity[COPY_PASTE_ERROR] */
     454           6 :       if (ctrl->cfg.verbose)
     455             :         {
     456           0 :           stinf ("\(fd %d): Sending exit cfg to server...\n", tsock->fd);
     457           0 :           vcl_test_cfg_dump (&tsock->cfg, 1 /* is_client */ );
     458             :         }
     459           6 :       (void) sock_test_write (tsock->fd, (uint8_t *) & tsock->cfg,
     460             :                               sizeof (tsock->cfg), &tsock->stats,
     461             :                               ctrl->cfg.verbose);
     462             :     }
     463             : 
     464           2 :   ctrl->cfg.test = VCL_TEST_TYPE_EXIT;
     465           2 :   if (ctrl->cfg.verbose)
     466             :     {
     467           0 :       stinf ("\n(fd %d): Sending exit cfg to server...\n", ctrl->fd);
     468           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     469             :     }
     470           2 :   (void) sock_test_write (ctrl->fd, (uint8_t *) & ctrl->cfg,
     471             :                           sizeof (ctrl->cfg), &ctrl->stats,
     472             :                           ctrl->cfg.verbose);
     473           2 :   stinf ("\nCLIENT: So long and thanks for all the fish!\n\n");
     474           2 :   sleep (1);
     475           2 : }
     476             : 
     477             : static int
     478           2 : sock_test_connect_test_sockets (uint32_t num_test_sockets)
     479             : {
     480           2 :   sock_client_main_t *scm = &sock_client_main;
     481           2 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     482             :   vcl_test_session_t *tsock;
     483             :   int i, rv;
     484             : 
     485           2 :   if (num_test_sockets < 1)
     486             :     {
     487           0 :       errno = EINVAL;
     488           0 :       return -1;
     489             :     }
     490             : 
     491           2 :   if (num_test_sockets < scm->num_test_sockets)
     492             :     {
     493           0 :       for (i = scm->num_test_sockets - 1; i >= num_test_sockets; i--)
     494             :         {
     495           0 :           tsock = &scm->test_socket[i];
     496           0 :           close (tsock->fd);
     497           0 :           free (tsock->txbuf);
     498           0 :           free (tsock->rxbuf);
     499             :         }
     500             :     }
     501             : 
     502           2 :   else if (num_test_sockets > scm->num_test_sockets)
     503             :     {
     504           2 :       tsock = realloc (scm->test_socket,
     505             :                        sizeof (vcl_test_session_t) * num_test_sockets);
     506           2 :       if (!tsock)
     507           0 :         stfail ("realloc()");
     508             : 
     509           2 :       memset (&tsock[scm->num_test_sockets], 0,
     510           2 :               sizeof (vcl_test_session_t) * (num_test_sockets -
     511           2 :                                              scm->num_test_sockets));
     512             : 
     513           2 :       scm->test_socket = tsock;
     514           8 :       for (i = scm->num_test_sockets; i < num_test_sockets; i++)
     515             :         {
     516           6 :           tsock = &scm->test_socket[i];
     517           6 :           tsock->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET,
     518           6 :                               ctrl->cfg.transport_udp ?
     519             :                               SOCK_DGRAM : SOCK_STREAM, 0);
     520             : 
     521           6 :           if (tsock->fd < 0)
     522           0 :             stfail ("socket()");
     523             : 
     524           6 :           rv = connect (tsock->fd, (struct sockaddr *) &scm->server_addr,
     525             :                         scm->server_addr_size);
     526             : 
     527           6 :           if (rv < 0)
     528           0 :             stfail ("connect()");
     529             : 
     530           6 :           if (fcntl (tsock->fd, F_SETFL, O_NONBLOCK) < 0)
     531           0 :             stfail ("fcntl");
     532             : 
     533           6 :           tsock->cfg = ctrl->cfg;
     534           6 :           vcl_test_session_buf_alloc (tsock);
     535           6 :           sock_test_cfg_sync (tsock);
     536             : 
     537           6 :           stinf ("(fd %d): Test socket %d connected", tsock->fd, i);
     538             :         }
     539             :     }
     540             : 
     541           2 :   scm->num_test_sockets = num_test_sockets;
     542           2 :   stinf ("All sockets (%d) connected!\n", scm->num_test_sockets + 1);
     543           2 :   return 0;
     544             : }
     545             : 
     546             : static void
     547           0 : cfg_txbuf_size_set (void)
     548             : {
     549           0 :   sock_client_main_t *scm = &sock_client_main;
     550           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     551           0 :   char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_TXBUF_SIZE);
     552           0 :   uint64_t txbuf_size = strtoull ((const char *) p, NULL, 10);
     553             : 
     554           0 :   if (txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN)
     555             :     {
     556           0 :       ctrl->cfg.txbuf_size = txbuf_size;
     557           0 :       ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
     558           0 :       vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ ,
     559           0 :                           (uint8_t **) & ctrl->txbuf, &ctrl->txbuf_size);
     560           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     561             :     }
     562             :   else
     563           0 :     stabrt ("Invalid txbuf size (%lu) < minimum buf size (%u)!",
     564             :             txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN);
     565           0 : }
     566             : 
     567             : static void
     568           0 : cfg_num_writes_set (void)
     569             : {
     570           0 :   sock_client_main_t *scm = &sock_client_main;
     571           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     572           0 :   char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_WRITES);
     573           0 :   uint32_t num_writes = strtoul ((const char *) p, NULL, 10);
     574             : 
     575           0 :   if (num_writes > 0)
     576             :     {
     577           0 :       ctrl->cfg.num_writes = num_writes;
     578           0 :       ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
     579           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     580             :     }
     581             :   else
     582           0 :     stabrt ("Invalid num writes: %u", num_writes);
     583           0 : }
     584             : 
     585             : static void
     586           0 : cfg_num_test_sockets_set (void)
     587             : {
     588           0 :   sock_client_main_t *scm = &sock_client_main;
     589           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     590           0 :   char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_NUM_TEST_SESS);
     591           0 :   uint32_t num_test_sockets = strtoul ((const char *) p, NULL, 10);
     592             : 
     593           0 :   if ((num_test_sockets > 0) &&
     594             :       (num_test_sockets <= VCL_TEST_CFG_MAX_TEST_SESS))
     595             :     {
     596           0 :       ctrl->cfg.num_test_sessions = num_test_sockets;
     597           0 :       sock_test_connect_test_sockets (num_test_sockets);
     598             : 
     599           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     600             :     }
     601             :   else
     602           0 :     stabrt ("Invalid num test sockets: %u, (%d max)\n", num_test_sockets,
     603             :             VCL_TEST_CFG_MAX_TEST_SESS);
     604           0 : }
     605             : 
     606             : static void
     607           0 : cfg_rxbuf_size_set (void)
     608             : {
     609           0 :   sock_client_main_t *scm = &sock_client_main;
     610           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     611           0 :   char *p = ctrl->txbuf + strlen (VCL_TEST_TOKEN_RXBUF_SIZE);
     612           0 :   uint64_t rxbuf_size = strtoull ((const char *) p, NULL, 10);
     613             : 
     614           0 :   if (rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN)
     615             :     {
     616           0 :       ctrl->cfg.rxbuf_size = rxbuf_size;
     617           0 :       vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ ,
     618           0 :                           (uint8_t **) & ctrl->rxbuf, &ctrl->rxbuf_size);
     619           0 :       vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     620             :     }
     621             :   else
     622           0 :     stabrt ("Invalid rxbuf size (%lu) < minimum buf size (%u)!",
     623             :             rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN);
     624           0 : }
     625             : 
     626             : static void
     627           0 : cfg_verbose_toggle (void)
     628             : {
     629           0 :   sock_client_main_t *scm = &sock_client_main;
     630           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     631             : 
     632           0 :   ctrl->cfg.verbose = ctrl->cfg.verbose ? 0 : 1;
     633           0 :   vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     634           0 : }
     635             : 
     636             : static vcl_test_t
     637           0 : parse_input ()
     638             : {
     639           0 :   sock_client_main_t *scm = &sock_client_main;
     640           0 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     641           0 :   vcl_test_t rv = VCL_TEST_TYPE_NONE;
     642             : 
     643           0 :   if (!strncmp (VCL_TEST_TOKEN_EXIT, ctrl->txbuf,
     644             :                 strlen (VCL_TEST_TOKEN_EXIT)))
     645           0 :     rv = VCL_TEST_TYPE_EXIT;
     646             : 
     647           0 :   else if (!strncmp (VCL_TEST_TOKEN_HELP, ctrl->txbuf,
     648             :                      strlen (VCL_TEST_TOKEN_HELP)))
     649           0 :     dump_help ();
     650             : 
     651           0 :   else if (!strncmp (VCL_TEST_TOKEN_SHOW_CFG, ctrl->txbuf,
     652             :                      strlen (VCL_TEST_TOKEN_SHOW_CFG)))
     653           0 :     scm->dump_cfg = 1;
     654             : 
     655           0 :   else if (!strncmp (VCL_TEST_TOKEN_VERBOSE, ctrl->txbuf,
     656             :                      strlen (VCL_TEST_TOKEN_VERBOSE)))
     657           0 :     cfg_verbose_toggle ();
     658             : 
     659           0 :   else if (!strncmp (VCL_TEST_TOKEN_TXBUF_SIZE, ctrl->txbuf,
     660             :                      strlen (VCL_TEST_TOKEN_TXBUF_SIZE)))
     661           0 :     cfg_txbuf_size_set ();
     662             : 
     663           0 :   else if (!strncmp (VCL_TEST_TOKEN_NUM_TEST_SESS, ctrl->txbuf,
     664             :                      strlen (VCL_TEST_TOKEN_NUM_TEST_SESS)))
     665           0 :     cfg_num_test_sockets_set ();
     666             : 
     667           0 :   else if (!strncmp (VCL_TEST_TOKEN_NUM_WRITES, ctrl->txbuf,
     668             :                      strlen (VCL_TEST_TOKEN_NUM_WRITES)))
     669           0 :     cfg_num_writes_set ();
     670             : 
     671           0 :   else if (!strncmp (VCL_TEST_TOKEN_RXBUF_SIZE, ctrl->txbuf,
     672             :                      strlen (VCL_TEST_TOKEN_RXBUF_SIZE)))
     673           0 :     cfg_rxbuf_size_set ();
     674             : 
     675           0 :   else if (!strncmp (VCL_TEST_TOKEN_RUN_UNI, ctrl->txbuf,
     676             :                      strlen (VCL_TEST_TOKEN_RUN_UNI)))
     677           0 :     rv = ctrl->cfg.test = VCL_TEST_TYPE_UNI;
     678             : 
     679           0 :   else if (!strncmp (VCL_TEST_TOKEN_RUN_BI, ctrl->txbuf,
     680             :                      strlen (VCL_TEST_TOKEN_RUN_BI)))
     681           0 :     rv = ctrl->cfg.test = VCL_TEST_TYPE_BI;
     682             : 
     683             :   else
     684           0 :     rv = VCL_TEST_TYPE_ECHO;
     685             : 
     686           0 :   return rv;
     687             : }
     688             : 
     689             : void
     690           0 : print_usage_and_exit (void)
     691             : {
     692           0 :   stinf ("sock_test_client [OPTIONS] <ipaddr> <port>\n"
     693             :          "  OPTIONS\n"
     694             :          "  -h               Print this message and exit.\n"
     695             :          "  -6               Use IPv6\n"
     696             :          "  -u               Use UDP transport layer\n"
     697             :          "  -c               Print test config before test.\n"
     698             :          "  -w <dir>         Write test results to <dir>.\n"
     699             :          "  -X               Exit after running test.\n"
     700             :          "  -E               Run Echo test.\n"
     701             :          "  -N <num-writes>  Test Cfg: number of writes.\n"
     702             :          "  -R <rxbuf-size>  Test Cfg: rx buffer size.\n"
     703             :          "  -T <txbuf-size>  Test Cfg: tx buffer size.\n"
     704             :          "  -U               Run Uni-directional test.\n"
     705             :          "  -B               Run Bi-directional test.\n"
     706             :          "  -V               Verbose mode.\n");
     707           0 :   exit (1);
     708             : }
     709             : 
     710             : int
     711           2 : main (int argc, char **argv)
     712             : {
     713           2 :   sock_client_main_t *scm = &sock_client_main;
     714           2 :   vcl_test_session_t *ctrl = &scm->ctrl_socket;
     715             :   int c, rv;
     716           2 :   vcl_test_t post_test = VCL_TEST_TYPE_NONE;
     717             : 
     718           2 :   vcl_test_cfg_init (&ctrl->cfg);
     719           2 :   vcl_test_session_buf_alloc (ctrl);
     720             : 
     721           2 :   opterr = 0;
     722           9 :   while ((c = getopt (argc, argv, "chn:w:XE:I:N:R:T:UBV6D")) != -1)
     723           7 :     switch (c)
     724             :       {
     725           0 :       case 'c':
     726           0 :         scm->dump_cfg = 1;
     727           0 :         break;
     728             : 
     729           0 :       case 's':
     730           0 :         if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1)
     731           0 :           if (sscanf (optarg, "%u", &ctrl->cfg.num_test_sessions) != 1)
     732             :             {
     733           0 :               stinf ("ERROR: Invalid value for option -%c!", c);
     734           0 :               print_usage_and_exit ();
     735             :             }
     736           0 :         if (!ctrl->cfg.num_test_sessions ||
     737           0 :             (ctrl->cfg.num_test_sessions > FD_SETSIZE))
     738             :           {
     739           0 :             stinf ("ERROR: Invalid number of "
     740             :                    "sockets (%d) specified for option -%c!\n"
     741             :                    "       Valid range is 1 - %d\n",
     742             :                    ctrl->cfg.num_test_sessions, c, FD_SETSIZE);
     743           0 :             print_usage_and_exit ();
     744             :           }
     745           0 :         break;
     746             : 
     747           0 :       case 'w':
     748           0 :         stinf ("Writing test results to files is TBD.\n");
     749           0 :         break;
     750             : 
     751           2 :       case 'X':
     752           2 :         post_test = VCL_TEST_TYPE_EXIT;
     753           2 :         break;
     754             : 
     755           0 :       case 'E':
     756           0 :         if (strlen (optarg) > ctrl->txbuf_size)
     757             :           {
     758           0 :             stinf ("ERROR: Option -%c value larger than txbuf size (%d)!",
     759             :                    optopt, ctrl->txbuf_size);
     760           0 :             print_usage_and_exit ();
     761             :           }
     762           0 :         strncpy (ctrl->txbuf, optarg, ctrl->txbuf_size);
     763           0 :         ctrl->cfg.test = VCL_TEST_TYPE_ECHO;
     764           0 :         break;
     765             : 
     766           1 :       case 'I':
     767           1 :         if (sscanf (optarg, "0x%x", &ctrl->cfg.num_test_sessions) != 1)
     768           1 :           if (sscanf (optarg, "%d", &ctrl->cfg.num_test_sessions) != 1)
     769             :             {
     770           0 :               stinf ("ERROR: Invalid value for option -%c!\n", c);
     771           0 :               print_usage_and_exit ();
     772             :             }
     773           1 :         if (ctrl->cfg.num_test_sessions > VCL_TEST_CFG_MAX_TEST_SESS)
     774             :           {
     775           0 :             stinf ("ERROR: value greater than max number test sockets (%d)!",
     776             :                    VCL_TEST_CFG_MAX_TEST_SESS);
     777           0 :             print_usage_and_exit ();
     778             :           }
     779           1 :         break;
     780             : 
     781           2 :       case 'N':
     782           2 :         if (sscanf (optarg, "0x%lx", &ctrl->cfg.num_writes) != 1)
     783           2 :           if (sscanf (optarg, "%ld", &ctrl->cfg.num_writes) != 1)
     784             :             {
     785           0 :               stinf ("ERROR: Invalid value for option -%c!", c);
     786           0 :               print_usage_and_exit ();
     787             :             }
     788           2 :         ctrl->cfg.total_bytes = ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
     789           2 :         break;
     790             : 
     791           0 :       case 'R':
     792           0 :         if (sscanf (optarg, "0x%lx", &ctrl->cfg.rxbuf_size) != 1)
     793           0 :           if (sscanf (optarg, "%ld", &ctrl->cfg.rxbuf_size) != 1)
     794             :             {
     795           0 :               stinf ("ERROR: Invalid value for option -%c!", c);
     796           0 :               print_usage_and_exit ();
     797             :             }
     798           0 :         if (ctrl->cfg.rxbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN)
     799             :           {
     800           0 :             ctrl->rxbuf_size = ctrl->cfg.rxbuf_size;
     801           0 :             vcl_test_buf_alloc (&ctrl->cfg, 1 /* is_rxbuf */ ,
     802           0 :                                 (uint8_t **) & ctrl->rxbuf,
     803             :                                 &ctrl->rxbuf_size);
     804             :           }
     805             :         else
     806             :           {
     807           0 :             stinf ("ERROR: rxbuf size (%lu) less than minumum (%u)\n",
     808             :                    ctrl->cfg.rxbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN);
     809           0 :             print_usage_and_exit ();
     810             :           }
     811             : 
     812           0 :         break;
     813             : 
     814           0 :       case 'T':
     815           0 :         if (sscanf (optarg, "0x%lx", &ctrl->cfg.txbuf_size) != 1)
     816           0 :           if (sscanf (optarg, "%ld", &ctrl->cfg.txbuf_size) != 1)
     817             :             {
     818           0 :               stinf ("ERROR: Invalid value for option -%c!", c);
     819           0 :               print_usage_and_exit ();
     820             :             }
     821           0 :         if (ctrl->cfg.txbuf_size >= VCL_TEST_CFG_BUF_SIZE_MIN)
     822             :           {
     823           0 :             ctrl->txbuf_size = ctrl->cfg.txbuf_size;
     824           0 :             vcl_test_buf_alloc (&ctrl->cfg, 0 /* is_rxbuf */ ,
     825           0 :                                 (uint8_t **) & ctrl->txbuf,
     826             :                                 &ctrl->txbuf_size);
     827           0 :             ctrl->cfg.total_bytes =
     828           0 :               ctrl->cfg.num_writes * ctrl->cfg.txbuf_size;
     829             :           }
     830             :         else
     831             :           {
     832           0 :             stinf ("ERROR: txbuf size (%lu) less than minumum (%u)!",
     833             :                    ctrl->cfg.txbuf_size, VCL_TEST_CFG_BUF_SIZE_MIN);
     834           0 :             print_usage_and_exit ();
     835             :           }
     836           0 :         break;
     837             : 
     838           1 :       case 'U':
     839           1 :         ctrl->cfg.test = VCL_TEST_TYPE_UNI;
     840           1 :         break;
     841             : 
     842           1 :       case 'B':
     843           1 :         ctrl->cfg.test = VCL_TEST_TYPE_BI;
     844           1 :         break;
     845             : 
     846           0 :       case 'V':
     847           0 :         ctrl->cfg.verbose = 1;
     848           0 :         break;
     849             : 
     850           0 :       case '6':
     851           0 :         ctrl->cfg.address_ip6 = 1;
     852           0 :         break;
     853             : 
     854           0 :       case 'D':
     855           0 :         ctrl->cfg.transport_udp = 1;
     856           0 :         break;
     857             : 
     858           0 :       case '?':
     859           0 :         switch (optopt)
     860             :           {
     861           0 :           case 'E':
     862             :           case 'I':
     863             :           case 'N':
     864             :           case 'R':
     865             :           case 'T':
     866             :           case 'w':
     867           0 :             stinf ("ERROR: Option -%c requires an argument.\n", optopt);
     868           0 :             break;
     869             : 
     870           0 :           default:
     871           0 :             if (isprint (optopt))
     872           0 :               stinf ("ERROR: Unknown option `-%c'.\n", optopt);
     873             :             else
     874           0 :               stinf ("ERROR: Unknown option character `\\x%x'.\n", optopt);
     875             :           }
     876             :         /* fall thru */
     877             :       case 'h':
     878             :       default:
     879           0 :         print_usage_and_exit ();
     880             :       }
     881             : 
     882           2 :   if (argc < (optind + 2))
     883             :     {
     884           0 :       stinf ("ERROR: Insufficient number of arguments!\n");
     885           0 :       print_usage_and_exit ();
     886             :     }
     887             : 
     888           2 :   ctrl->fd = socket (ctrl->cfg.address_ip6 ? AF_INET6 : AF_INET,
     889           2 :                      ctrl->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM, 0);
     890             : 
     891           2 :   if (ctrl->fd < 0)
     892           0 :     stfail ("socket()");
     893             : 
     894           2 :   memset (&scm->server_addr, 0, sizeof (scm->server_addr));
     895           2 :   if (ctrl->cfg.address_ip6)
     896             :     {
     897           0 :       struct sockaddr_in6 *server_addr =
     898             :         (struct sockaddr_in6 *) &scm->server_addr;
     899           0 :       scm->server_addr_size = sizeof (*server_addr);
     900           0 :       server_addr->sin6_family = AF_INET6;
     901           0 :       inet_pton (AF_INET6, argv[optind++], &(server_addr->sin6_addr));
     902           0 :       server_addr->sin6_port = htons (atoi (argv[optind]));
     903             :     }
     904             :   else
     905             :     {
     906           2 :       struct sockaddr_in *server_addr =
     907             :         (struct sockaddr_in *) &scm->server_addr;
     908           2 :       scm->server_addr_size = sizeof (*server_addr);
     909           2 :       server_addr->sin_family = AF_INET;
     910           2 :       inet_pton (AF_INET, argv[optind++], &(server_addr->sin_addr));
     911           2 :       server_addr->sin_port = htons (atoi (argv[optind]));
     912             :     }
     913             : 
     914             :   do
     915             :     {
     916           2 :       stinf ("\nConnecting to server...\n");
     917             : 
     918           2 :       rv = connect (ctrl->fd, (struct sockaddr *) &scm->server_addr,
     919             :                     scm->server_addr_size);
     920             : 
     921           2 :       if (rv < 0)
     922           0 :         stfail ("connect()");
     923             : 
     924           2 :       sock_test_cfg_sync (ctrl);
     925           2 :       stinf ("(fd %d): Control socket connected.\n", ctrl->fd);
     926             :     }
     927           2 :   while (rv < 0);
     928             : 
     929           2 :   sock_test_connect_test_sockets (ctrl->cfg.num_test_sessions);
     930             : 
     931           4 :   while (ctrl->cfg.test != VCL_TEST_TYPE_EXIT)
     932             :     {
     933           2 :       if (scm->dump_cfg)
     934             :         {
     935           0 :           vcl_test_cfg_dump (&ctrl->cfg, 1 /* is_client */ );
     936           0 :           scm->dump_cfg = 0;
     937             :         }
     938             : 
     939           2 :       switch (ctrl->cfg.test)
     940             :         {
     941           0 :         case VCL_TEST_TYPE_ECHO:
     942           0 :           echo_test_client ();
     943           0 :           break;
     944             : 
     945           2 :         case VCL_TEST_TYPE_UNI:
     946             :         case VCL_TEST_TYPE_BI:
     947           2 :           stream_test_client (ctrl->cfg.test);
     948           2 :           break;
     949             : 
     950           0 :         case VCL_TEST_TYPE_EXIT:
     951           0 :           continue;
     952             : 
     953           0 :         case VCL_TEST_TYPE_NONE:
     954             :         default:
     955           0 :           break;
     956             :         }
     957           2 :       switch (post_test)
     958             :         {
     959           2 :         case VCL_TEST_TYPE_EXIT:
     960           2 :           switch (ctrl->cfg.test)
     961             :             {
     962           2 :             case VCL_TEST_TYPE_EXIT:
     963             :             case VCL_TEST_TYPE_UNI:
     964             :             case VCL_TEST_TYPE_BI:
     965             :             case VCL_TEST_TYPE_ECHO:
     966           2 :               ctrl->cfg.test = VCL_TEST_TYPE_EXIT;
     967           2 :               continue;
     968             : 
     969           0 :             case VCL_TEST_TYPE_NONE:
     970             :             default:
     971           0 :               break;
     972             :             }
     973           0 :           break;
     974             : 
     975           0 :         case VCL_TEST_TYPE_NONE:
     976             :         case VCL_TEST_TYPE_ECHO:
     977             :         case VCL_TEST_TYPE_UNI:
     978             :         case VCL_TEST_TYPE_BI:
     979             :         default:
     980           0 :           break;
     981             :         }
     982             : 
     983           0 :       memset (ctrl->txbuf, 0, ctrl->txbuf_size);
     984           0 :       memset (ctrl->rxbuf, 0, ctrl->rxbuf_size);
     985             : 
     986           0 :       stinf ("\nType some characters and hit <return>\n"
     987             :              "('" VCL_TEST_TOKEN_HELP "' for help): ");
     988             : 
     989           0 :       if (fgets (ctrl->txbuf, ctrl->txbuf_size, stdin) != NULL)
     990             :         {
     991           0 :           if (strlen (ctrl->txbuf) == 1)
     992             :             {
     993           0 :               stinf ("\nNothing to send!  Please try again...\n");
     994           0 :               continue;
     995             :             }
     996           0 :           ctrl->txbuf[strlen (ctrl->txbuf) - 1] = 0;      // chomp the newline.
     997             : 
     998             :           /* Parse input for keywords */
     999           0 :           ctrl->cfg.test = parse_input ();
    1000             :         }
    1001             :     }
    1002             : 
    1003           2 :   exit_client ();
    1004           2 :   close (ctrl->fd);
    1005           2 :   return (scm->af_unix_echo_tx == scm->af_unix_echo_rx) ? 0 : -1;
    1006             : }
    1007             : 
    1008             : /*
    1009             :  * fd.io coding-style-patch-verification: ON
    1010             :  *
    1011             :  * Local Variables:
    1012             :  * eval: (c-set-style "gnu")
    1013             :  * End:
    1014             :  */

Generated by: LCOV version 1.14