LCOV - code coverage report
Current view: top level - plugins/hs_apps/vcl - sock_test_server.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 191 305 62.6 %
Date: 2023-07-05 22:20:52 Functions: 11 14 78.6 %

          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 <sys/types.h>
      19             : #include <sys/socket.h>
      20             : #include <stdio.h>
      21             : #include <string.h>
      22             : #include <time.h>
      23             : #include <ctype.h>
      24             : #include <hs_apps/vcl/sock_test.h>
      25             : #include <sys/stat.h>
      26             : #include <fcntl.h>
      27             : #include <sys/ioctl.h>
      28             : #include <sys/epoll.h>
      29             : #include <sys/un.h>
      30             : 
      31             : #define SOCK_SERVER_MAX_TEST_CONN  10
      32             : #define SOCK_SERVER_MAX_EPOLL_EVENTS 10
      33             : 
      34             : typedef struct
      35             : {
      36             :   uint8_t is_alloc;
      37             :   int fd;
      38             :   uint8_t *buf;
      39             :   uint32_t buf_size;
      40             :   vcl_test_cfg_t cfg;
      41             :   vcl_test_stats_t stats;
      42             : } sock_server_conn_t;
      43             : 
      44             : typedef struct
      45             : {
      46             :   uint32_t port;
      47             :   uint32_t address_ip6;
      48             :   uint32_t transport_udp;
      49             : } sock_server_cfg_t;
      50             : 
      51             : typedef struct
      52             : {
      53             :   int listen_fd;
      54             :   sock_server_cfg_t cfg;
      55             :   int epfd;
      56             :   struct epoll_event listen_ev;
      57             :   struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS];
      58             :   int af_unix_listen_fd;
      59             :   int af_unix_fd;
      60             :   struct epoll_event af_unix_listen_ev;
      61             :   struct sockaddr_un serveraddr;
      62             :   uint32_t af_unix_xacts;
      63             :   size_t num_conn;
      64             :   size_t conn_pool_size;
      65             :   sock_server_conn_t *conn_pool;
      66             :   int nfds;
      67             :   fd_set rd_fdset;
      68             :   fd_set wr_fdset;
      69             :   struct timeval timeout;
      70             : } sock_server_main_t;
      71             : 
      72             : sock_server_main_t sock_server_main;
      73             : 
      74             : static inline void
      75           1 : conn_pool_expand (size_t expand_size)
      76             : {
      77           1 :   sock_server_main_t *ssm = &sock_server_main;
      78             :   sock_server_conn_t *conn_pool;
      79           1 :   size_t new_size = ssm->conn_pool_size + expand_size;
      80             :   int i;
      81             : 
      82           1 :   conn_pool = realloc (ssm->conn_pool, new_size * sizeof (*ssm->conn_pool));
      83           1 :   if (!conn_pool)
      84           0 :     stfail ("conn_pool_expand()");
      85             : 
      86          12 :   for (i = ssm->conn_pool_size; i < new_size; i++)
      87             :     {
      88          11 :       sock_server_conn_t *conn = &conn_pool[i];
      89          11 :       memset (conn, 0, sizeof (*conn));
      90          11 :       vcl_test_cfg_init (&conn->cfg);
      91          11 :       vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ , &conn->buf,
      92             :                           &conn->buf_size);
      93          11 :       conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
      94             :     }
      95             : 
      96           1 :   ssm->conn_pool = conn_pool;
      97           1 :   ssm->conn_pool_size = new_size;
      98           1 : }
      99             : 
     100             : static inline sock_server_conn_t *
     101           2 : conn_pool_alloc (void)
     102             : {
     103           2 :   sock_server_main_t *ssm = &sock_server_main;
     104             :   int i;
     105             : 
     106           3 :   for (i = 0; i < ssm->conn_pool_size; i++)
     107             :     {
     108           3 :       if (!ssm->conn_pool[i].is_alloc)
     109             :         {
     110           2 :           ssm->conn_pool[i].is_alloc = 1;
     111           2 :           return (&ssm->conn_pool[i]);
     112             :         }
     113             :     }
     114             : 
     115           0 :   return 0;
     116             : }
     117             : 
     118             : static inline void
     119           2 : conn_pool_free (sock_server_conn_t * conn)
     120             : {
     121           2 :   conn->fd = 0;
     122           2 :   conn->is_alloc = 0;
     123           2 : }
     124             : 
     125             : static inline void
     126           6 : sync_config_and_reply (sock_server_conn_t * conn, vcl_test_cfg_t * rx_cfg)
     127             : {
     128           6 :   conn->cfg = *rx_cfg;
     129           6 :   vcl_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ ,
     130             :                       &conn->buf, &conn->buf_size);
     131           6 :   conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
     132             : 
     133           6 :   if (conn->cfg.verbose)
     134             :     {
     135           0 :       stinf ("(fd %d): Replying to cfg message!\n", conn->fd);
     136           0 :       vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
     137             :     }
     138           6 :   (void) sock_test_write (conn->fd, (uint8_t *) & conn->cfg,
     139             :                           sizeof (conn->cfg), NULL, conn->cfg.verbose);
     140           6 : }
     141             : 
     142             : static void
     143           5 : stream_test_server_start_stop (sock_server_conn_t * conn,
     144             :                                vcl_test_cfg_t * rx_cfg)
     145             : {
     146           5 :   sock_server_main_t *ssm = &sock_server_main;
     147           5 :   int client_fd = conn->fd;
     148           5 :   vcl_test_t test = rx_cfg->test;
     149             : 
     150           5 :   if (rx_cfg->ctrl_handle == conn->fd)
     151             :     {
     152             :       int i;
     153           1 :       clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
     154             : 
     155          12 :       for (i = 0; i < ssm->conn_pool_size; i++)
     156             :         {
     157          11 :           sock_server_conn_t *tc = &ssm->conn_pool[i];
     158             : 
     159          11 :           if (tc->cfg.ctrl_handle == conn->fd)
     160             :             {
     161           2 :               vcl_test_stats_accumulate (&conn->stats, &tc->stats);
     162             : 
     163           2 :               if (conn->cfg.verbose)
     164             :                 {
     165             :                   static char buf[64];
     166             : 
     167           0 :                   snprintf (buf, sizeof (buf), "SERVER (fd %d) RESULTS",
     168             :                             tc->fd);
     169           0 :                   vcl_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ ,
     170             :                                        test == VCL_TEST_TYPE_BI
     171             :                                        /* show tx */ ,
     172           0 :                                        conn->cfg.verbose);
     173             :                 }
     174             :             }
     175             :         }
     176             : 
     177           1 :       vcl_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ ,
     178             :                            (test == VCL_TEST_TYPE_BI) /* show_tx */ ,
     179           1 :                            conn->cfg.verbose);
     180           1 :       vcl_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
     181           1 :       if (conn->cfg.verbose)
     182             :         {
     183           0 :           stinf ("  sock server main\n"
     184             :                  VCL_TEST_SEPARATOR_STRING
     185             :                  "       buf:  %p\n"
     186             :                  "  buf size:  %u (0x%08x)\n"
     187             :                  VCL_TEST_SEPARATOR_STRING,
     188             :                  conn->buf, conn->buf_size, conn->buf_size);
     189             :         }
     190             : 
     191           1 :       sync_config_and_reply (conn, rx_cfg);
     192           1 :       stinf ("SERVER (fd %d): %s-directional Stream Test Complete!\n"
     193             :              SOCK_TEST_BANNER_STRING "\n", conn->fd,
     194             :              test == VCL_TEST_TYPE_BI ? "Bi" : "Uni");
     195             :     }
     196             :   else
     197             :     {
     198           4 :       stinf (SOCK_TEST_BANNER_STRING
     199             :              "SERVER (fd %d): %s-directional Stream Test!\n"
     200             :              "  Sending client the test cfg to start streaming data...\n",
     201             :              client_fd, test == VCL_TEST_TYPE_BI ? "Bi" : "Uni");
     202             : 
     203           4 :       rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd :
     204             :         rx_cfg->ctrl_handle;
     205             : 
     206           4 :       sync_config_and_reply (conn, rx_cfg);
     207             : 
     208             :       /* read the 1st chunk, record start time */
     209           4 :       memset (&conn->stats, 0, sizeof (conn->stats));
     210           4 :       clock_gettime (CLOCK_REALTIME, &conn->stats.start);
     211             :     }
     212           5 : }
     213             : 
     214             : 
     215             : static inline void
     216         242 : stream_test_server (sock_server_conn_t * conn, int rx_bytes)
     217             : {
     218         242 :   int client_fd = conn->fd;
     219         242 :   vcl_test_t test = conn->cfg.test;
     220             : 
     221         242 :   if (test == VCL_TEST_TYPE_BI)
     222         242 :     (void) sock_test_write (client_fd, conn->buf, rx_bytes, &conn->stats,
     223             :                             conn->cfg.verbose);
     224             : 
     225         242 :   if (conn->stats.rx_bytes >= conn->cfg.total_bytes)
     226             :     {
     227           1 :       clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
     228             :     }
     229         242 : }
     230             : 
     231             : static inline void
     232           0 : af_unix_echo (void)
     233             : {
     234           0 :   sock_server_main_t *ssm = &sock_server_main;
     235             :   int af_unix_client_fd, rv;
     236             :   uint8_t buffer[256];
     237           0 :   size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1;
     238             : 
     239           0 :   af_unix_client_fd = accept (ssm->af_unix_listen_fd,
     240             :                               (struct sockaddr *) NULL, NULL);
     241           0 :   if (af_unix_client_fd < 0)
     242           0 :     stfail ("af_unix_echo accept()");
     243             : 
     244           0 :   stinf ("Got an AF_UNIX connection -- fd = %d (0x%08x)!",
     245             :          af_unix_client_fd, af_unix_client_fd);
     246             : 
     247           0 :   memset (buffer, 0, sizeof (buffer));
     248             : 
     249           0 :   rv = read (af_unix_client_fd, buffer, nbytes);
     250           0 :   if (rv < 0)
     251           0 :     stfail ("af_unix_echo read()");
     252             : 
     253             :   /* Make the buffer is NULL-terminated. */
     254           0 :   buffer[sizeof (buffer) - 1] = 0;
     255           0 :   stinf ("(AF_UNIX): RX (%d bytes) - '%s'", rv, buffer);
     256             : 
     257           0 :   if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes))
     258             :     {
     259           0 :       rv = write (af_unix_client_fd, buffer, nbytes);
     260           0 :       if (rv < 0)
     261           0 :         stfail ("af_unix_echo write()");
     262           0 :       stinf ("(AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
     263           0 :       ssm->af_unix_xacts++;
     264             :     }
     265           0 :   close (af_unix_client_fd);
     266           0 : }
     267             : 
     268             : static inline void
     269           2 : new_client (void)
     270             : {
     271           2 :   sock_server_main_t *ssm = &sock_server_main;
     272             :   int client_fd;
     273             :   sock_server_conn_t *conn;
     274             : 
     275           2 :   if (ssm->conn_pool_size < (ssm->num_conn + SOCK_SERVER_MAX_TEST_CONN + 1))
     276           0 :     conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
     277             : 
     278           2 :   conn = conn_pool_alloc ();
     279           2 :   if (!conn)
     280           0 :     stfail ("No free connections!");
     281             : 
     282           2 :   client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL);
     283           2 :   if (client_fd < 0)
     284           0 :     stfail ("new_client accept()");
     285             : 
     286           2 :   stinf ("Got a connection -- fd = %d (0x%08x)!\n", client_fd, client_fd);
     287           2 :   if (fcntl (client_fd, F_SETFL, O_NONBLOCK) < 0)
     288           0 :     stfail ("fcntl()");
     289             : 
     290           2 :   conn->fd = client_fd;
     291             : 
     292             :   struct epoll_event ev;
     293             :   int rv;
     294             : 
     295           2 :   ev.events = EPOLLET | EPOLLIN;
     296           2 :   ev.data.u64 = conn - ssm->conn_pool;
     297           2 :   rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
     298             : 
     299           2 :   if (rv < 0)
     300           0 :     stfail ("new_client epoll_ctl()");
     301             : 
     302           2 :   ssm->nfds++;
     303           2 : }
     304             : 
     305             : static int
     306           1 : socket_server_echo_af_unix_init (sock_server_main_t * ssm)
     307             : {
     308             :   int rv;
     309             : 
     310           1 :   if (ssm->af_unix_listen_fd > 0)
     311           0 :     return 0;
     312             : 
     313           1 :   unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
     314           1 :   ssm->af_unix_listen_fd = socket (AF_UNIX, SOCK_STREAM, 0);
     315           1 :   if (ssm->af_unix_listen_fd < 0)
     316           0 :     stfail ("echo_af_unix_init socket()");
     317             : 
     318           1 :   memset (&ssm->serveraddr, 0, sizeof (ssm->serveraddr));
     319           1 :   ssm->serveraddr.sun_family = AF_UNIX;
     320           1 :   strncpy (ssm->serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME,
     321             :            sizeof (ssm->serveraddr.sun_path));
     322             : 
     323           1 :   rv = bind (ssm->af_unix_listen_fd, (struct sockaddr *) &ssm->serveraddr,
     324           1 :              SUN_LEN (&ssm->serveraddr));
     325           1 :   if (rv < 0)
     326           0 :     stfail ("echo_af_unix_init bind()");
     327             : 
     328           1 :   rv = listen (ssm->af_unix_listen_fd, 10);
     329           1 :   if (rv < 0)
     330           0 :     stfail ("echo_af_unix_init listen()");
     331             : 
     332           1 :   ssm->af_unix_listen_ev.events = EPOLLET | EPOLLIN;
     333           1 :   ssm->af_unix_listen_ev.data.u32 = SOCK_TEST_AF_UNIX_ACCEPT_DATA;
     334           1 :   rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->af_unix_listen_fd,
     335             :                   &ssm->af_unix_listen_ev);
     336           1 :   if (rv < 0)
     337           0 :     stfail ("echo_af_unix_init epoll_ctl()");
     338             : 
     339           1 :   return 0;
     340             : }
     341             : 
     342             : void
     343           0 : print_usage_and_exit (void)
     344             : {
     345           0 :   fprintf (stderr,
     346             :            "sock_test_server [OPTIONS] <port>\n"
     347             :            "  OPTIONS\n"
     348             :            "  -h               Print this message and exit.\n"
     349             :            "  -6               Use IPv6\n"
     350             :            "  -u               Use UDP transport layer\n");
     351           0 :   exit (1);
     352             : }
     353             : 
     354             : 
     355             : static void
     356           0 : sts_server_echo (sock_server_conn_t * conn, int rx_bytes)
     357             : {
     358             :   int tx_bytes, nbytes, pos;
     359             : 
     360             :   /* If it looks vaguely like a string make sure it's terminated */
     361           0 :   pos = rx_bytes < conn->buf_size ? rx_bytes : conn->buf_size - 1;
     362           0 :   ((char *) conn->buf)[pos] = 0;
     363             : 
     364           0 :   if (conn->cfg.verbose)
     365           0 :     stinf ("(fd %d): Echoing back\n", conn->fd);
     366             : 
     367           0 :   nbytes = strlen ((const char *) conn->buf) + 1;
     368             : 
     369           0 :   tx_bytes = sock_test_write (conn->fd, conn->buf, nbytes, &conn->stats,
     370             :                               conn->cfg.verbose);
     371           0 :   if (tx_bytes >= 0)
     372           0 :     stinf ("(fd %d): TX (%d bytes) - '%s'\n", conn->fd, tx_bytes, conn->buf);
     373           0 : }
     374             : 
     375             : static int
     376           8 : sts_handle_cfg (vcl_test_cfg_t * rx_cfg, sock_server_conn_t * conn,
     377             :                 int rx_bytes)
     378             : {
     379           8 :   sock_server_main_t *ssm = &sock_server_main;
     380             : 
     381           8 :   if (rx_cfg->verbose)
     382             :     {
     383           0 :       stinf ("(fd %d): Received a cfg message!\n", conn->fd);
     384           0 :       vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
     385             :     }
     386             : 
     387           8 :   if (rx_bytes != sizeof (*rx_cfg))
     388             :     {
     389           0 :       stinf ("(fd %d): Invalid cfg message size (%d) expected %lu!", conn->fd,
     390             :              rx_bytes, sizeof (*rx_cfg));
     391           0 :       conn->cfg.rxbuf_size = 0;
     392           0 :       conn->cfg.num_writes = 0;
     393           0 :       if (conn->cfg.verbose)
     394             :         {
     395           0 :           stinf ("(fd %d): Replying to cfg message!\n", conn->fd);
     396           0 :           vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
     397             :         }
     398           0 :       sock_test_write (conn->fd, (uint8_t *) & conn->cfg, sizeof (conn->cfg),
     399             :                        NULL, conn->cfg.verbose);
     400           0 :       return -1;
     401             :     }
     402             : 
     403           8 :   switch (rx_cfg->test)
     404             :     {
     405           0 :     case VCL_TEST_TYPE_NONE:
     406           0 :       sync_config_and_reply (conn, rx_cfg);
     407           0 :       break;
     408             : 
     409           1 :     case VCL_TEST_TYPE_ECHO:
     410           1 :       if (socket_server_echo_af_unix_init (ssm))
     411           0 :         goto done;
     412             : 
     413           1 :       sync_config_and_reply (conn, rx_cfg);
     414           1 :       break;
     415             : 
     416           5 :     case VCL_TEST_TYPE_BI:
     417             :     case VCL_TEST_TYPE_UNI:
     418           5 :       stream_test_server_start_stop (conn, rx_cfg);
     419           5 :       break;
     420             : 
     421           2 :     case VCL_TEST_TYPE_EXIT:
     422           2 :       stinf ("Have a great day connection %d!", conn->fd);
     423           2 :       close (conn->fd);
     424           2 :       conn_pool_free (conn);
     425           2 :       stinf ("Closed client fd %d", conn->fd);
     426           2 :       ssm->nfds--;
     427           2 :       break;
     428             : 
     429           0 :     default:
     430           0 :       stinf ("ERROR: Unknown test type!\n");
     431           0 :       vcl_test_cfg_dump (rx_cfg, 0 /* is_client */ );
     432           0 :       break;
     433             :     }
     434             : 
     435           8 : done:
     436           8 :   return 0;
     437             : }
     438             : 
     439             : static int
     440         250 : sts_conn_expect_config (sock_server_conn_t * conn)
     441             : {
     442         250 :   if (conn->cfg.test == VCL_TEST_TYPE_ECHO)
     443           1 :     return 1;
     444             : 
     445         249 :   return (conn->stats.rx_bytes < 128
     446         249 :           || conn->stats.rx_bytes > conn->cfg.total_bytes);
     447             : }
     448             : 
     449             : int
     450           1 : main (int argc, char **argv)
     451             : {
     452           1 :   int client_fd, rv, main_rv = 0, rx_bytes, c, v, i;
     453           1 :   sock_server_main_t *ssm = &sock_server_main;
     454             :   sock_server_conn_t *conn;
     455             :   vcl_test_cfg_t *rx_cfg;
     456             :   struct sockaddr_storage servaddr;
     457           1 :   uint16_t port = VCL_TEST_SERVER_PORT;
     458             :   uint32_t servaddr_size;
     459             : 
     460           1 :   opterr = 0;
     461           1 :   while ((c = getopt (argc, argv, "6D")) != -1)
     462           0 :     switch (c)
     463             :       {
     464           0 :       case '6':
     465           0 :         ssm->cfg.address_ip6 = 1;
     466           0 :         break;
     467             : 
     468           0 :       case 'D':
     469           0 :         ssm->cfg.transport_udp = 1;
     470           0 :         break;
     471             : 
     472           0 :       case '?':
     473           0 :         switch (optopt)
     474             :           {
     475             :           default:
     476           0 :             if (isprint (optopt))
     477           0 :               stinf ("ERROR: Unknown option `-%c'", optopt);
     478             :             else
     479           0 :               stinf ("ERROR: Unknown option character `\\x%x'.\n", optopt);
     480             :           }
     481             :         /* fall thru */
     482             :       case 'h':
     483             :       default:
     484           0 :         print_usage_and_exit ();
     485             :       }
     486             : 
     487           1 :   if (argc < (optind + 1))
     488             :     {
     489           0 :       stinf ("ERROR: Insufficient number of arguments!\n");
     490           0 :       print_usage_and_exit ();
     491             :     }
     492             : 
     493           1 :   if (sscanf (argv[optind], "%d", &v) == 1)
     494           1 :     port = (uint16_t) v;
     495             :   else
     496             :     {
     497           0 :       stinf ("ERROR: Invalid port (%s)!\n", argv[optind]);
     498           0 :       print_usage_and_exit ();
     499             :     }
     500             : 
     501           1 :   conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
     502             : 
     503           1 :   ssm->listen_fd = socket (ssm->cfg.address_ip6 ? AF_INET6 : AF_INET,
     504           1 :                            ssm->cfg.transport_udp ? SOCK_DGRAM : SOCK_STREAM,
     505             :                            0);
     506             : 
     507           1 :   if (ssm->listen_fd < 0)
     508           0 :     stfail ("main listen()");
     509             : 
     510           1 :   memset (&servaddr, 0, sizeof (servaddr));
     511             : 
     512           1 :   if (ssm->cfg.address_ip6)
     513             :     {
     514           0 :       struct sockaddr_in6 *server_addr = (struct sockaddr_in6 *) &servaddr;
     515           0 :       servaddr_size = sizeof (*server_addr);
     516           0 :       server_addr->sin6_family = AF_INET6;
     517           0 :       server_addr->sin6_addr = in6addr_any;
     518           0 :       server_addr->sin6_port = htons (port);
     519             :     }
     520             :   else
     521             :     {
     522           1 :       struct sockaddr_in *server_addr = (struct sockaddr_in *) &servaddr;
     523           1 :       servaddr_size = sizeof (*server_addr);
     524           1 :       server_addr->sin_family = AF_INET;
     525           1 :       server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
     526           1 :       server_addr->sin_port = htons (port);
     527             :     }
     528             : 
     529           1 :   rv = bind (ssm->listen_fd, (struct sockaddr *) &servaddr, servaddr_size);
     530           1 :   if (rv < 0)
     531           0 :     stfail ("main bind()");
     532             : 
     533           1 :   rv = fcntl (ssm->listen_fd, F_SETFL, O_NONBLOCK);
     534           1 :   if (rv < 0)
     535           0 :     stfail ("main fcntl()");
     536             : 
     537           1 :   rv = listen (ssm->listen_fd, 10);
     538           1 :   if (rv < 0)
     539           0 :     stfail ("main listen()");
     540             : 
     541           1 :   ssm->epfd = epoll_create (1);
     542           1 :   if (ssm->epfd < 0)
     543           0 :     stfail ("main epoll_create()");
     544             : 
     545           1 :   ssm->listen_ev.events = EPOLLET | EPOLLIN;
     546           1 :   ssm->listen_ev.data.u32 = ~0;
     547             : 
     548           1 :   rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, &ssm->listen_ev);
     549           1 :   if (rv < 0)
     550           0 :     stfail ("main epoll_ctl()");
     551             : 
     552           1 :   stinf ("Waiting for a client to connect on port %d...\n", port);
     553             : 
     554             :   while (1)
     555         250 :     {
     556             :       int num_ev;
     557         251 :       num_ev = epoll_wait (ssm->epfd, ssm->wait_events,
     558             :                            SOCK_SERVER_MAX_EPOLL_EVENTS, 60000);
     559         251 :       if (num_ev < 0)
     560           0 :         stfail ("main epoll_wait()");
     561             : 
     562         251 :       if (num_ev == 0)
     563             :         {
     564           0 :           stinf ("epoll_wait() timeout!\n");
     565           0 :           continue;
     566             :         }
     567         502 :       for (i = 0; i < num_ev; i++)
     568             :         {
     569         252 :           conn = &ssm->conn_pool[ssm->wait_events[i].data.u32];
     570         252 :           if (ssm->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
     571             :             {
     572           0 :               close (conn->fd);
     573           0 :               continue;
     574             :             }
     575         252 :           if (ssm->wait_events[i].data.u32 == ~0)
     576             :             {
     577           2 :               new_client ();
     578           2 :               continue;
     579             :             }
     580         250 :           else if (ssm->wait_events[i].data.u32 ==
     581             :                    SOCK_TEST_AF_UNIX_ACCEPT_DATA)
     582             :             {
     583           0 :               af_unix_echo ();
     584           0 :               continue;
     585             :             }
     586         250 :           client_fd = conn->fd;
     587             : 
     588         250 :           if (EPOLLIN & ssm->wait_events[i].events)
     589             :             {
     590         250 :             read_again:
     591         250 :               rx_bytes = sock_test_read (client_fd, conn->buf,
     592             :                                          conn->buf_size, &conn->stats);
     593             : 
     594         250 :               if (rx_bytes <= 0)
     595             :                 {
     596           0 :                   if (errno == ECONNRESET)
     597             :                     {
     598           0 :                       stinf ("Connection reset by peer\n");
     599           0 :                       main_rv = -1;
     600           0 :                       goto done;
     601             :                     }
     602             :                   else
     603           0 :                     continue;
     604             :                 }
     605             : 
     606         250 :               if (sts_conn_expect_config (conn))
     607             :                 {
     608           8 :                   rx_cfg = (vcl_test_cfg_t *) conn->buf;
     609           8 :                   if (rx_cfg->magic == VCL_TEST_CFG_CTRL_MAGIC)
     610             :                     {
     611           8 :                       sts_handle_cfg (rx_cfg, conn, rx_bytes);
     612           8 :                       if (!ssm->nfds)
     613             :                         {
     614           1 :                           stinf ("All client connections closed.\n\nSERVER: "
     615             :                                  "May the force be with you!\n\n");
     616           1 :                           goto done;
     617             :                         }
     618           7 :                       continue;
     619             :                     }
     620             :                 }
     621             : 
     622         242 :               if ((conn->cfg.test == VCL_TEST_TYPE_UNI)
     623         242 :                   || (conn->cfg.test == VCL_TEST_TYPE_BI))
     624             :                 {
     625         242 :                   stream_test_server (conn, rx_bytes);
     626         242 :                   if (ioctl (conn->fd, FIONREAD))
     627           0 :                     goto read_again;
     628         242 :                   continue;
     629             :                 }
     630           0 :               else if (isascii (conn->buf[0]))
     631             :                 {
     632           0 :                   sts_server_echo (conn, rx_bytes);
     633             :                 }
     634             :               else
     635             :                 {
     636           0 :                   stwrn ("FIFO not drained! extra bytes %d", rx_bytes);
     637             :                 }
     638             :             }
     639             :         }
     640             :     }
     641             : 
     642           1 : done:
     643           1 :   close (ssm->listen_fd);
     644           1 :   close (ssm->af_unix_listen_fd);
     645           1 :   unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
     646             : 
     647           1 :   if (ssm->conn_pool)
     648           1 :     free (ssm->conn_pool);
     649             : 
     650           1 :   return main_rv;
     651             : }
     652             : 
     653             : /*
     654             :  * fd.io coding-style-patch-verification: ON
     655             :  *
     656             :  * Local Variables:
     657             :  * eval: (c-set-style "gnu")
     658             :  * End:
     659             :  */

Generated by: LCOV version 1.14