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 sprintf (buf,
"SERVER (fd %d) RESULTS", tc->
fd);
256 printf (
" sock server main\n" 259 " buf size: %u (0x%08x)\n" 265 printf (
"\nSERVER (fd %d): %s-directional Stream Test Complete!\n" 272 "SERVER (fd %d): %s-directional Stream Test!\n" 273 " Sending client the test cfg to start streaming data...\n",
282 memset (&conn->
stats, 0, sizeof (conn->
stats));
283 clock_gettime (CLOCK_REALTIME, &conn->
stats.
start);
291 int client_fd = conn->
fd;
300 clock_gettime (CLOCK_REALTIME, &conn->
stats.
stop);
304 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 309 int af_unix_client_fd;
317 (
struct sockaddr *)
NULL, NULL, NULL);
320 (
struct sockaddr *) NULL, NULL);
322 if (af_unix_client_fd < 0)
325 perror (
"ERROR in af_unix_accept()");
326 fprintf (stderr,
"SERVER: ERROR: accept failed " 327 "(errno = %d)!\n", errno_val);
331 printf (
"SERVER: Got an AF_UNIX connection -- fd = %d (0x%08x)!\n",
332 af_unix_client_fd, af_unix_client_fd);
334 memset (buffer, 0,
sizeof (buffer));
336 rv = read (af_unix_client_fd, buffer, nbytes);
340 perror (
"ERROR in af_unix_echo(): read() failed");
341 fprintf (stderr,
"SERVER: ERROR: read(af_unix_client_fd %d (0x%x), " 342 "nbytes %lu) failed (errno = %d)!\n", af_unix_client_fd,
343 af_unix_client_fd, nbytes, errno_val);
347 buffer[
sizeof (buffer) - 1] = 0;
348 printf (
"SERVER (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
352 rv = write (af_unix_client_fd, buffer, nbytes);
356 perror (
"ERROR in af_unix_echo(): write() failed");
358 "SERVER: ERROR: write(af_unix_client_fd %d (0x%x), " 359 "\"%s\", nbytes %ld) failed (errno = %d)!\n",
360 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
364 printf (
"SERVER (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
368 close (af_unix_client_fd);
386 fprintf (stderr,
"\nSERVER: ERROR: No free connections!\n");
391 client_fd = vppcom_session_accept (ssm->
listen_fd, &conn->endpt, 0);
395 client_fd = accept4 (ssm->
listen_fd, (
struct sockaddr *)
NULL, NULL, NULL);
397 client_fd = accept (ssm->
listen_fd, (
struct sockaddr *) NULL, NULL);
403 perror (
"ERROR in new_client()");
404 fprintf (stderr,
"SERVER: ERROR: accept failed " 405 "(errno = %d)!\n", errno_val);
409 printf (
"SERVER: Got a connection -- fd = %d (0x%08x)!\n",
410 client_fd, client_fd);
412 conn->
fd = client_fd;
414 #if ! SOCK_SERVER_USE_EPOLL 415 conn_fdset_set (conn, &ssm->
rd_fdset);
419 struct epoll_event ev;
425 rv = vppcom_epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
429 rv = epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, client_fd, &ev);
435 perror (
"ERROR in new_client()");
436 fprintf (stderr,
"SERVER: ERROR: epoll_ctl failed (errno = %d)!\n",
449 "sock_test_server [OPTIONS] <port>\n" 451 " -h Print this message and exit.\n" 453 " -u Use UDP transport layer\n");
461 int client_fd, rv, main_rv = 0;
462 int tx_bytes, rx_bytes, nbytes;
466 uint64_t xtra_bytes = 0;
467 struct sockaddr_storage servaddr;
471 #if ! SOCK_SERVER_USE_EPOLL 472 fd_set _rfdset, *rfdset = &_rfdset;
475 vppcom_endpt_t endpt;
477 uint32_t servaddr_size;
478 #if ! SOCK_SERVER_USE_EPOLL 479 fd_set _wfdset, *wfdset = &_wfdset;
484 while ((c = getopt (argc, argv,
"6D")) != -1)
499 if (isprint (optopt))
500 fprintf (stderr,
"SERVER: ERROR: Unknown " 501 "option `-%c'.\n", optopt);
503 fprintf (stderr,
"SERVER: ERROR: Unknown " 504 "option character `\\x%x'.\n", optopt);
512 if (argc < (optind + 1))
514 fprintf (stderr,
"SERVER: ERROR: Insufficient number of arguments!\n");
518 if (sscanf (argv[optind],
"%d", &v) == 1)
522 fprintf (stderr,
"SERVER: ERROR: Invalid port (%s)!\n", argv[optind]);
529 rv = vppcom_app_create (
"vcl_test_server");
546 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 547 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
552 perror (
"ERROR in main(): socket(AF_UNIX) failed");
554 "SERVER: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed " 555 "(errno = %d)!\n", errno_val);
561 strcpy (ssm->
serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME);
568 perror (
"ERROR in main(): bind(SOCK_TEST_AF_UNIX_FILENAME) failed");
569 fprintf (stderr,
"SERVER: ERROR: bind() fd %d, \"%s\": " 571 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
573 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
581 perror (
"ERROR in main(): listen(AF_UNIX) failed");
582 fprintf (stderr,
"SERVER: ERROR: listen() fd %d, \"%s\": " 584 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
586 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
594 perror (
"ERROR in main()");
595 fprintf (stderr,
"SERVER: ERROR: socket() failed " 596 "(errno = %d)!\n", errno_val);
600 memset (&servaddr, 0,
sizeof (servaddr));
604 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) &servaddr;
606 servaddr_size =
sizeof (*server_addr);
608 server_addr->sin6_family = AF_INET6;
609 server_addr->sin6_addr = in6addr_any;
610 server_addr->sin6_port = htons (port);
614 struct sockaddr_in *server_addr = (
struct sockaddr_in *) &servaddr;
616 servaddr_size =
sizeof (*server_addr);
618 server_addr->sin_family = AF_INET;
619 server_addr->sin_addr.s_addr = htonl (INADDR_ANY);
620 server_addr->sin_port = htons (port);
626 struct sockaddr_in6 *server_addr = (
struct sockaddr_in6 *) &servaddr;
628 endpt.ip = (uint8_t *) & server_addr->sin6_addr;
629 endpt.port = (uint16_t) server_addr->sin6_port;
633 struct sockaddr_in *server_addr = (
struct sockaddr_in *) &servaddr;
635 endpt.ip = (uint8_t *) & server_addr->sin_addr;
636 endpt.port = (uint16_t) server_addr->sin_port;
639 rv = vppcom_session_bind (ssm->
listen_fd, &endpt);
646 rv = bind (ssm->
listen_fd, (
struct sockaddr *) &servaddr, servaddr_size);
651 perror (
"ERROR in main()");
652 fprintf (stderr,
"SERVER: ERROR: bind failed (errno = %d)!\n",
656 if (fcntl (ssm->
listen_fd, F_SETFL, O_NONBLOCK) < 0)
659 perror (
"ERROR in main()");
660 fprintf (stderr,
"SERVER: ERROR: fcntl failed (errno = %d)!\n",
666 rv = vppcom_session_listen (ssm->
listen_fd, 10);
678 perror (
"ERROR in main()");
679 fprintf (stderr,
"SERVER: ERROR: listen failed " 680 "(errno = %d)!\n", errno_val);
684 #if ! SOCK_SERVER_USE_EPOLL 694 ssm->
epfd = vppcom_epoll_create ();
698 ssm->
epfd = epoll_create (1);
703 perror (
"ERROR in main()");
704 fprintf (stderr,
"SERVER: ERROR: epoll_create failed (errno = %d)!\n",
712 rv = vppcom_epoll_ctl (ssm->
epfd, EPOLL_CTL_ADD, ssm->
listen_fd,
724 perror (
"ERROR in main(): mixed epoll_ctl(EPOLL_CTL_ADD)");
725 fprintf (stderr,
"SERVER: ERROR: mixed epoll_ctl(epfd %d (0x%x), " 726 "EPOLL_CTL_ADD, af_unix_listen_fd %d (0x%x), EPOLLIN) failed " 727 "(errno = %d)!\n", ssm->
epfd, ssm->
epfd,
730 unlink ((
const char *) SOCK_TEST_AF_UNIX_FILENAME);
739 perror (
"ERROR in main()");
740 fprintf (stderr,
"SERVER: ERROR: epoll_ctl failed " 741 "(errno = %d)!\n", errno_val);
746 printf (
"\nSERVER: Waiting for a client to connect on port %d...\n", port);
750 #if ! SOCK_SERVER_USE_EPOLL 754 rv = vppcom_select (ssm->
nfds, (
unsigned long *) rfdset,
NULL,
NULL, 0);
757 struct timeval timeout;
760 rv = select (ssm->
nfds, rfdset, wfdset,
NULL, &timeout);
766 fprintf (stderr,
"\nSERVER: ERROR: select() failed -- aborting!\n");
795 perror (
"epoll_wait()");
796 fprintf (stderr,
"\nSERVER: ERROR: epoll_wait() " 797 "failed -- aborting!\n");
803 fprintf (stderr,
"\nSERVER: epoll_wait() timeout!\n");
806 for (i = 0; i < num_ev; i++)
809 if (ssm->
wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
812 vppcom_session_close (conn->
fd);
823 #if !defined (VCL_TEST) 832 client_fd = conn->
fd;
834 #if ! SOCK_SERVER_USE_EPOLL 835 if (FD_ISSET (client_fd, rfdset))
850 printf (
"SERVER (fd %d): Received a cfg message!\n",
855 if (rx_bytes !=
sizeof (*rx_cfg))
857 printf (
"SERVER (fd %d): Invalid cfg message " 858 "size (%d)!\n Should be %lu bytes.\n",
859 client_fd, rx_bytes,
sizeof (*rx_cfg));
864 printf (
"SERVER (fd %d): Replying to " 865 "cfg message!\n", client_fd);
874 switch (rx_cfg->
test)
887 printf (
"SERVER: Have a great day, " 888 "connection %d!\n", client_fd);
890 vppcom_session_close (client_fd);
895 printf (
"SERVER: Closed client fd %d\n", client_fd);
896 #if ! SOCK_SERVER_USE_EPOLL 903 printf (
"SERVER: All client connections " 904 "closed.\n\nSERVER: " 905 "May the force be with you!\n\n");
912 "SERVER: ERROR: Unknown test type!\n");
923 if (ioctl (conn->
fd, FIONREAD))
928 else if (isascii (conn->
buf[0]))
931 ((
char *) conn->
buf)[rx_bytes <
934 printf (
"SERVER (fd %d): RX (%d bytes) - '%s'\n",
935 conn->
fd, rx_bytes, conn->
buf);
940 if (errno == ECONNRESET)
942 printf (
"\nSERVER: Connection reset by remote peer.\n" 943 " Y'all have a great day now!\n\n");
950 if (isascii (conn->
buf[0]))
955 ((
char *) conn->
buf)[rx_bytes <
959 fprintf (stderr,
"SERVER: ERROR: " 960 "FIFO not drained in previous test!\n" 961 " extra chunks %u (0x%x)\n" 962 " extra bytes %lu (0x%lx)\n",
963 xtra, xtra, xtra_bytes, xtra_bytes);
969 printf (
"SERVER (fd %d): Echoing back\n", client_fd);
971 nbytes = strlen ((
const char *) conn->
buf) + 1;
974 nbytes, &conn->
stats,
977 printf (
"SERVER (fd %d): TX (%d bytes) - '%s'\n",
978 conn->
fd, tx_bytes, conn->
buf);
984 xtra_bytes += rx_bytes;
993 vppcom_app_destroy ();
997 #if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST) 999 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)