18 #include <sys/types.h> 19 #include <sys/socket.h> 27 #include <sys/ioctl.h> 29 #define SOCK_SERVER_USE_EPOLL 1 30 #define VPPCOM_SESSION_ATTR_UNIT_TEST 0 32 #if SOCK_SERVER_USE_EPOLL 33 #include <sys/epoll.h> 34 #if !defined(VCL_TEST) 40 #if VPPCOM_SESSION_ATTR_UNIT_TEST 41 #define BUFLEN sizeof (uint64_t) * 16 43 uint32_t buflen = BUFLEN;
44 uint32_t *
flags = (uint32_t *) buffer;
69 #define SOCK_SERVER_MAX_TEST_CONN 10 70 #define SOCK_SERVER_MAX_EPOLL_EVENTS 10 75 #if SOCK_SERVER_USE_EPOLL 77 struct epoll_event listen_ev;
79 #if !defined (VCL_TEST) 82 struct epoll_event af_unix_listen_ev;
83 struct sockaddr_un serveraddr;
93 struct timeval timeout;
98 #if ! SOCK_SERVER_USE_EPOLL 105 for (nfds = i = 0; i < FD_SETSIZE; i++)
118 FD_SET (conn->
fd, fdset);
119 ssm->
nfds = get_nfds ();
127 FD_CLR (conn->
fd, fdset);
128 ssm->
nfds = get_nfds ();
146 memset (conn, 0,
sizeof (*conn));
158 int errno_val = errno;
159 perror (
"ERROR in conn_pool_expand()");
160 fprintf (stderr,
"SERVER: ERROR: Memory allocation " 161 "failed (errno = %d)!\n", errno_val);
189 #if ! SOCK_SERVER_USE_EPOLL 192 conn_fdset_clr (conn, &ssm->
rd_fdset);
193 conn_fdset_clr (conn, &ssm->
wr_fdset);
209 printf (
"\nSERVER (fd %d): Replying to cfg message!\n", conn->
fd);
221 int client_fd = conn->
fd;
227 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
241 snprintf (buf,
sizeof (buf),
"SERVER (fd %d) RESULTS",
257 printf (
" sock server main\n" 260 " buf size: %u (0x%08x)\n" 266 printf (
"\nSERVER (fd %d): %s-directional Stream Test Complete!\n" 273 "SERVER (fd %d): %s-directional Stream Test!\n" 274 " Sending client the test cfg to start streaming data...\n",
283 memset (&conn->
stats, 0, sizeof (conn->
stats));
284 clock_gettime (CLOCK_REALTIME, &conn->
stats.
start);
292 int client_fd = conn->
fd;
301 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
305 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 310 int af_unix_client_fd;
318 (
struct sockaddr *) NULL, NULL, NULL);
321 (
struct sockaddr *) NULL, NULL);
323 if (af_unix_client_fd < 0)
326 perror (
"ERROR in af_unix_accept()");
327 fprintf (stderr,
"SERVER: ERROR: accept failed " 328 "(errno = %d)!\n", errno_val);
332 printf (
"SERVER: Got an AF_UNIX connection -- fd = %d (0x%08x)!\n",
333 af_unix_client_fd, af_unix_client_fd);
335 memset (buffer, 0,
sizeof (buffer));
337 rv = read (af_unix_client_fd, buffer, nbytes);
341 perror (
"ERROR in af_unix_echo(): read() failed");
342 fprintf (stderr,
"SERVER: ERROR: read(af_unix_client_fd %d (0x%x), " 343 "nbytes %lu) failed (errno = %d)!\n", af_unix_client_fd,
344 af_unix_client_fd, nbytes, errno_val);
348 buffer[
sizeof (buffer) - 1] = 0;
349 printf (
"SERVER (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
353 rv = write (af_unix_client_fd, buffer, nbytes);
357 perror (
"ERROR in af_unix_echo(): write() failed");
359 "SERVER: ERROR: write(af_unix_client_fd %d (0x%x), " 360 "\"%s\", nbytes %ld) failed (errno = %d)!\n",
361 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
365 printf (
"SERVER (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
369 close (af_unix_client_fd);
387 fprintf (stderr,
"\nSERVER: ERROR: No free connections!\n");
392 client_fd = vppcom_session_accept (ssm->
listen_fd, &conn->endpt, 0);
396 client_fd = accept4 (ssm->
listen_fd, (
struct sockaddr *) NULL, NULL, NULL);
398 client_fd = accept (ssm->
listen_fd, (
struct sockaddr *) NULL, NULL);
404 perror (
"ERROR in new_client()");
405 fprintf (stderr,
"SERVER: ERROR: accept failed " 406 "(errno = %d)!\n", errno_val);
410 printf (
"SERVER: Got a connection -- fd = %d (0x%08x)!\n",
411 client_fd, client_fd);
413 conn->
fd = client_fd;
415 #if ! SOCK_SERVER_USE_EPOLL 416 conn_fdset_set (conn, &ssm->
rd_fdset);
420 struct epoll_event ev;
426 rv = vppcom_epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
430 rv = epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
436 perror (
"ERROR in new_client()");
437 fprintf (stderr,
"SERVER: ERROR: epoll_ctl failed (errno = %d)!\n",
450 "sock_test_server [OPTIONS] <port>\n" 452 " -h Print this message and exit.\n" 454 " -u Use UDP transport layer\n");
462 int client_fd, rv, main_rv = 0;
463 int tx_bytes, rx_bytes, nbytes;
467 uint64_t xtra_bytes = 0;
468 struct sockaddr_storage servaddr;
472 #if ! SOCK_SERVER_USE_EPOLL 473 fd_set _rfdset, *rfdset = &_rfdset;
476 vppcom_endpt_t endpt;
478 uint32_t servaddr_size;
479 #if ! SOCK_SERVER_USE_EPOLL 480 fd_set _wfdset, *wfdset = &_wfdset;
485 while ((c = getopt (argc, argv,
"6D")) != -1)
500 if (isprint (optopt))
501 fprintf (stderr,
"SERVER: ERROR: Unknown " 502 "option `-%c'.\n", optopt);
504 fprintf (stderr,
"SERVER: ERROR: Unknown " 505 "option character `\\x%x'.\n", optopt);
513 if (argc < (optind + 1))
515 fprintf (stderr,
"SERVER: ERROR: Insufficient number of arguments!\n");
519 if (sscanf (argv[optind],
"%d", &v) == 1)
523 fprintf (stderr,
"SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
530 rv = vppcom_app_create (
"vcl_test_server");
547 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 548 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
553 perror (
"ERROR in main(): socket(AF_UNIX) failed");
555 "SERVER: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed " 556 "(errno = %d)!\n", errno_val);
562 strncpy (ssm->
serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME,
570 perror (
"ERROR in main(): bind(SOCK_TEST_AF_UNIX_FILENAME) failed");
571 fprintf (stderr,
"SERVER: ERROR: bind() fd %d, \"%s\": " 573 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
575 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
583 perror (
"ERROR in main(): listen(AF_UNIX) failed");
584 fprintf (stderr,
"SERVER: ERROR: listen() fd %d, \"%s\": " 586 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
588 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
596 perror (
"ERROR in main()");
597 fprintf (stderr,
"SERVER: ERROR: socket() failed " 598 "(errno = %d)!\n", errno_val);
602 memset (&servaddr, 0,
sizeof (servaddr));
606 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) &servaddr;
608 servaddr_size =
sizeof (*server_addr);
610 server_addr->sin6_family = AF_INET6;
611 server_addr->sin6_addr = in6addr_any;
612 server_addr->sin6_port = htons (port);
616 struct sockaddr_in *server_addr = (
struct sockaddr_in *) &servaddr;
618 servaddr_size =
sizeof (*server_addr);
620 server_addr->sin_family = AF_INET;
621 server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
622 server_addr->sin_port = htons (port);
628 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) &servaddr;
630 endpt.ip = (uint8_t *) & server_addr->sin6_addr;
631 endpt.port = (uint16_t) server_addr->sin6_port;
635 struct sockaddr_in *server_addr = (
struct sockaddr_in *) &servaddr;
637 endpt.ip = (uint8_t *) & server_addr->sin_addr;
638 endpt.port = (uint16_t) server_addr->sin_port;
641 rv = vppcom_session_bind (ssm->
listen_fd, &endpt);
648 rv = bind (ssm->
listen_fd, (
struct sockaddr *) &servaddr, servaddr_size);
653 perror (
"ERROR in main()");
654 fprintf (stderr,
"SERVER: ERROR: bind failed (errno = %d)!\n",
658 if (fcntl (ssm->
listen_fd, F_SETFL, O_NONBLOCK) < 0)
661 perror (
"ERROR in main()");
662 fprintf (stderr,
"SERVER: ERROR: fcntl failed (errno = %d)!\n",
668 rv = vppcom_session_listen (ssm->
listen_fd, 10);
680 perror (
"ERROR in main()");
681 fprintf (stderr,
"SERVER: ERROR: listen failed " 682 "(errno = %d)!\n", errno_val);
686 #if ! SOCK_SERVER_USE_EPOLL 696 ssm->
epfd = vppcom_epoll_create ();
700 ssm->
epfd = epoll_create (1);
705 perror (
"ERROR in main()");
706 fprintf (stderr,
"SERVER: ERROR: epoll_create failed (errno = %d)!\n",
714 rv = vppcom_epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, ssm->
listen_fd,
726 perror (
"ERROR in main(): mixed epoll_ctl(EPOLL_CTL_ADD)");
727 fprintf (stderr,
"SERVER: ERROR: mixed epoll_ctl(epfd %d (0x%x), " 728 "EPOLL_CTL_ADD, af_unix_listen_fd %d (0x%x), EPOLLIN) failed " 729 "(errno = %d)!\n", ssm->
epfd, ssm->
epfd,
732 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
741 perror (
"ERROR in main()");
742 fprintf (stderr,
"SERVER: ERROR: epoll_ctl failed " 743 "(errno = %d)!\n", errno_val);
748 printf (
"\nSERVER: Waiting for a client to connect on port %d...\n", port);
752 #if ! SOCK_SERVER_USE_EPOLL 756 rv = vppcom_select (ssm->
nfds, (
unsigned long *) rfdset, NULL, NULL, 0);
759 struct timeval timeout;
762 rv = select (ssm->
nfds, rfdset, wfdset, NULL, &timeout);
768 fprintf (stderr,
"\nSERVER: ERROR: select() failed -- aborting!\n");
797 perror (
"epoll_wait()");
798 fprintf (stderr,
"\nSERVER: ERROR: epoll_wait() " 799 "failed -- aborting!\n");
805 fprintf (stderr,
"\nSERVER: epoll_wait() timeout!\n");
808 for (i = 0; i < num_ev; i++)
811 if (ssm->
wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
814 vppcom_session_close (conn->
fd);
825 #if !defined (VCL_TEST) 834 client_fd = conn->
fd;
836 #if ! SOCK_SERVER_USE_EPOLL 837 if (FD_ISSET (client_fd, rfdset))
852 printf (
"SERVER (fd %d): Received a cfg message!\n",
857 if (rx_bytes !=
sizeof (*rx_cfg))
859 printf (
"SERVER (fd %d): Invalid cfg message " 860 "size (%d)!\n Should be %lu bytes.\n",
861 client_fd, rx_bytes,
sizeof (*rx_cfg));
866 printf (
"SERVER (fd %d): Replying to " 867 "cfg message!\n", client_fd);
871 sizeof (conn->
cfg), NULL,
876 switch (rx_cfg->
test)
889 printf (
"SERVER: Have a great day, " 890 "connection %d!\n", client_fd);
892 vppcom_session_close (client_fd);
897 printf (
"SERVER: Closed client fd %d\n", client_fd);
898 #if ! SOCK_SERVER_USE_EPOLL 905 printf (
"SERVER: All client connections " 906 "closed.\n\nSERVER: " 907 "May the force be with you!\n\n");
914 "SERVER: ERROR: Unknown test type!\n");
925 if (ioctl (conn->
fd, FIONREAD))
930 else if (isascii (conn->
buf[0]))
933 ((
char *) conn->
buf)[rx_bytes <
936 printf (
"SERVER (fd %d): RX (%d bytes) - '%s'\n",
937 conn->
fd, rx_bytes, conn->
buf);
942 if (errno == ECONNRESET)
944 printf (
"\nSERVER: Connection reset by remote peer.\n" 945 " Y'all have a great day now!\n\n");
952 if (isascii (conn->
buf[0]))
957 ((
char *) conn->
buf)[rx_bytes <
961 fprintf (stderr,
"SERVER: ERROR: " 962 "FIFO not drained in previous test!\n" 963 " extra chunks %u (0x%x)\n" 964 " extra bytes %lu (0x%lx)\n",
965 xtra, xtra, xtra_bytes, xtra_bytes);
971 printf (
"SERVER (fd %d): Echoing back\n", client_fd);
973 nbytes = strlen ((
const char *) conn->
buf) + 1;
976 nbytes, &conn->
stats,
979 printf (
"SERVER (fd %d): TX (%d bytes) - '%s'\n",
980 conn->
fd, tx_bytes, conn->
buf);
986 xtra_bytes += rx_bytes;
995 vppcom_app_destroy ();
999 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 1001 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
static void new_client(void)
static int sock_test_read(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats)
static void conn_pool_expand(size_t expand_size)
#define SOCK_TEST_AF_UNIX_ACCEPT_DATA
Optimized string handling code, including c11-compliant "safe C library" variants.
static void sync_config_and_reply(sock_server_conn_t *conn, vcl_test_cfg_t *rx_cfg)
static void conn_pool_free(sock_server_conn_t *conn)
struct sockaddr_un serveraddr
#define VCL_TEST_SERVER_PORT
#define SOCK_TEST_BANNER_STRING
static void vcl_test_stats_dump(char *header, vcl_test_stats_t *stats, uint8_t show_rx, uint8_t show_tx, uint8_t verbose)
static int sock_test_write(int fd, uint8_t *buf, uint32_t nbytes, vcl_test_stats_t *stats, uint32_t verbose)
#define SOCK_SERVER_MAX_TEST_CONN
#define VCL_TEST_SEPARATOR_STRING
static void vcl_test_cfg_dump(vcl_test_cfg_t *cfg, uint8_t is_client)
struct epoll_event listen_ev
static void stream_test_server_start_stop(sock_server_conn_t *conn, vcl_test_cfg_t *rx_cfg)
#define VCL_TEST_CFG_CTRL_MAGIC
struct epoll_event af_unix_listen_ev
sock_server_main_t sock_server_main
static void vcl_test_cfg_init(vcl_test_cfg_t *cfg)
static void vcl_test_buf_alloc(vcl_test_cfg_t *cfg, uint8_t is_rxbuf, uint8_t **buf, uint32_t *bufsize)
#define SOCK_TEST_MIXED_EPOLL_DATA
static sock_server_conn_t * conn_pool_alloc(void)
void print_usage_and_exit(void)
static void af_unix_echo(void)
int main(int argc, char **argv)
#define SOCK_SERVER_MAX_EPOLL_EVENTS
static void vcl_test_stats_accumulate(vcl_test_stats_t *accum, vcl_test_stats_t *incr)
struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS]
sock_server_conn_t * conn_pool
static void stream_test_server(sock_server_conn_t *conn, int rx_bytes)