blob: 39ffb8e2f484c124af10c82b51053856f9dbc488 [file] [log] [blame]
Dave Wallace543852a2017-08-03 02:11:34 -04001/*
2 * Copyright (c) 2017 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>
Dave Wallace5c7cf1c2017-10-24 04:12:18 -040024#include <vcl/sock_test.h>
Dave Wallace35830af2017-10-09 01:43:42 -040025#include <sys/stat.h>
26#include <fcntl.h>
Dave Wallace543852a2017-08-03 02:11:34 -040027
Dave Wallacef7f809c2017-10-03 01:48:42 -040028#define SOCK_SERVER_USE_EPOLL 1
Dave Wallace35830af2017-10-09 01:43:42 -040029#define VPPCOM_SESSION_ATTR_UNIT_TEST 0
Dave Wallacef7f809c2017-10-03 01:48:42 -040030
31#if SOCK_SERVER_USE_EPOLL
32#include <sys/epoll.h>
Dave Wallace3ee1fe12018-02-23 01:09:11 -050033#if !defined(VCL_TEST)
34#include <sys/un.h>
35#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -040036#endif
37
Dave Wallace35830af2017-10-09 01:43:42 -040038#ifdef VCL_TEST
39#if VPPCOM_SESSION_ATTR_UNIT_TEST
40#define BUFLEN sizeof (uint64_t) * 16
41uint64_t buffer[16];
42uint32_t buflen = BUFLEN;
43uint32_t *flags = (uint32_t *) buffer;
44#endif
45#endif
46
Dave Wallace543852a2017-08-03 02:11:34 -040047typedef struct
48{
49 uint8_t is_alloc;
50 int fd;
51 uint8_t *buf;
52 uint32_t buf_size;
53 sock_test_cfg_t cfg;
54 sock_test_stats_t stats;
55#ifdef VCL_TEST
56 vppcom_endpt_t endpt;
57 uint8_t ip[16];
58#endif
59} sock_server_conn_t;
60
61#define SOCK_SERVER_MAX_TEST_CONN 10
Dave Wallacef7f809c2017-10-03 01:48:42 -040062#define SOCK_SERVER_MAX_EPOLL_EVENTS 10
Dave Wallace543852a2017-08-03 02:11:34 -040063typedef struct
64{
65 int listen_fd;
Dave Wallacef7f809c2017-10-03 01:48:42 -040066#if SOCK_SERVER_USE_EPOLL
67 int epfd;
68 struct epoll_event listen_ev;
69 struct epoll_event wait_events[SOCK_SERVER_MAX_EPOLL_EVENTS];
Dave Wallace3ee1fe12018-02-23 01:09:11 -050070#if !defined (VCL_TEST)
71 int af_unix_listen_fd;
72 int af_unix_fd;
73 struct epoll_event af_unix_listen_ev;
74 struct sockaddr_un serveraddr;
75 uint32_t af_unix_xacts;
76#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -040077#endif
Dave Wallace543852a2017-08-03 02:11:34 -040078 size_t num_conn;
79 size_t conn_pool_size;
80 sock_server_conn_t *conn_pool;
81 int nfds;
82 fd_set rd_fdset;
83 fd_set wr_fdset;
84 struct timeval timeout;
85} sock_server_main_t;
86
87sock_server_main_t sock_server_main;
88
Dave Wallacef7f809c2017-10-03 01:48:42 -040089#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -040090static inline int
91get_nfds (void)
92{
93 sock_server_main_t *ssm = &sock_server_main;
94 int i, nfds;
95
96 for (nfds = i = 0; i < FD_SETSIZE; i++)
97 {
98 if (FD_ISSET (i, &ssm->rd_fdset) || FD_ISSET (i, &ssm->wr_fdset))
99 nfds = i + 1;
100 }
101 return nfds;
102}
103
104static inline void
105conn_fdset_set (sock_server_conn_t * conn, fd_set * fdset)
106{
107 sock_server_main_t *ssm = &sock_server_main;
108
109 FD_SET (conn->fd, fdset);
110 ssm->nfds = get_nfds ();
111}
112
113static inline void
114conn_fdset_clr (sock_server_conn_t * conn, fd_set * fdset)
115{
116 sock_server_main_t *ssm = &sock_server_main;
117
118 FD_CLR (conn->fd, fdset);
119 ssm->nfds = get_nfds ();
120}
Dave Wallacef7f809c2017-10-03 01:48:42 -0400121#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400122
123static inline void
124conn_pool_expand (size_t expand_size)
125{
126 sock_server_main_t *ssm = &sock_server_main;
127 sock_server_conn_t *conn_pool;
128 size_t new_size = ssm->conn_pool_size + expand_size;
129 int i;
130
131 conn_pool = realloc (ssm->conn_pool, new_size * sizeof (*ssm->conn_pool));
132 if (conn_pool)
133 {
134 for (i = ssm->conn_pool_size; i < new_size; i++)
135 {
136 sock_server_conn_t *conn = &conn_pool[i];
137 memset (conn, 0, sizeof (*conn));
138 sock_test_cfg_init (&conn->cfg);
139 sock_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ ,
140 &conn->buf, &conn->buf_size);
141 conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
142 }
143
144 ssm->conn_pool = conn_pool;
145 ssm->conn_pool_size = new_size;
146 }
147 else
148 {
149 int errno_val = errno;
150 perror ("ERROR in conn_pool_expand()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500151 fprintf (stderr, "SERVER: ERROR: Memory allocation "
152 "failed (errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400153 }
154}
155
156static inline sock_server_conn_t *
157conn_pool_alloc (void)
158{
159 sock_server_main_t *ssm = &sock_server_main;
160 int i;
161
162 for (i = 0; i < ssm->conn_pool_size; i++)
163 {
164 if (!ssm->conn_pool[i].is_alloc)
165 {
166#ifdef VCL_TEST
167 ssm->conn_pool[i].endpt.ip = ssm->conn_pool[i].ip;
168#endif
169 ssm->conn_pool[i].is_alloc = 1;
170 return (&ssm->conn_pool[i]);
171 }
172 }
173
174 return 0;
175}
176
177static inline void
178conn_pool_free (sock_server_conn_t * conn)
179{
Dave Wallacef7f809c2017-10-03 01:48:42 -0400180#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400181 sock_server_main_t *ssm = &sock_server_main;
182
183 conn_fdset_clr (conn, &ssm->rd_fdset);
184 conn_fdset_clr (conn, &ssm->wr_fdset);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400185#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400186 conn->fd = 0;
187 conn->is_alloc = 0;
188}
189
190static inline void
191sync_config_and_reply (sock_server_conn_t * conn, sock_test_cfg_t * rx_cfg)
192{
193 conn->cfg = *rx_cfg;
194 sock_test_buf_alloc (&conn->cfg, 1 /* is_rxbuf */ ,
195 &conn->buf, &conn->buf_size);
196 conn->cfg.txbuf_size = conn->cfg.rxbuf_size;
197
198 if (conn->cfg.verbose)
199 {
200 printf ("\nSERVER (fd %d): Replying to cfg message!\n", conn->fd);
201 sock_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
202 }
203 (void) sock_test_write (conn->fd, (uint8_t *) & conn->cfg,
204 sizeof (conn->cfg), NULL, conn->cfg.verbose);
205}
206
207static void
208stream_test_server_start_stop (sock_server_conn_t * conn,
209 sock_test_cfg_t * rx_cfg)
210{
211 sock_server_main_t *ssm = &sock_server_main;
212 int client_fd = conn->fd;
213 sock_test_t test = rx_cfg->test;
214
215 if (rx_cfg->ctrl_handle == conn->fd)
216 {
217 int i;
218 clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
219
220 for (i = 0; i < ssm->conn_pool_size; i++)
221 {
222 sock_server_conn_t *tc = &ssm->conn_pool[i];
223
224 if (tc->cfg.ctrl_handle == conn->fd)
225 {
226 sock_test_stats_accumulate (&conn->stats, &tc->stats);
227
228 if (conn->cfg.verbose)
229 {
230 static char buf[64];
231
232 sprintf (buf, "SERVER (fd %d) RESULTS", tc->fd);
233 sock_test_stats_dump (buf, &tc->stats, 1 /* show_rx */ ,
234 test == SOCK_TEST_TYPE_BI
235 /* show tx */ ,
236 conn->cfg.verbose);
237 }
238 }
239 }
240
241 sock_test_stats_dump ("SERVER RESULTS", &conn->stats, 1 /* show_rx */ ,
242 (test == SOCK_TEST_TYPE_BI) /* show_tx */ ,
243 conn->cfg.verbose);
244 sock_test_cfg_dump (&conn->cfg, 0 /* is_client */ );
245 if (conn->cfg.verbose)
246 {
247 printf (" sock server main\n"
248 SOCK_TEST_SEPARATOR_STRING
249 " buf: %p\n"
250 " buf size: %u (0x%08x)\n"
251 SOCK_TEST_SEPARATOR_STRING,
252 conn->buf, conn->buf_size, conn->buf_size);
253 }
254
255 sync_config_and_reply (conn, rx_cfg);
256 printf ("\nSERVER (fd %d): %s-directional Stream Test Complete!\n"
257 SOCK_TEST_BANNER_STRING "\n", conn->fd,
258 test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni");
259 }
260 else
261 {
262 printf ("\n" SOCK_TEST_BANNER_STRING
263 "SERVER (fd %d): %s-directional Stream Test!\n"
264 " Sending client the test cfg to start streaming data...\n",
265 client_fd, test == SOCK_TEST_TYPE_BI ? "Bi" : "Uni");
266
267 rx_cfg->ctrl_handle = (rx_cfg->ctrl_handle == ~0) ? conn->fd :
268 rx_cfg->ctrl_handle;
269
270 sync_config_and_reply (conn, rx_cfg);
271
272 /* read the 1st chunk, record start time */
273 memset (&conn->stats, 0, sizeof (conn->stats));
274 clock_gettime (CLOCK_REALTIME, &conn->stats.start);
275 }
276}
277
278
279static inline void
280stream_test_server (sock_server_conn_t * conn, int rx_bytes)
281{
282 int client_fd = conn->fd;
283 sock_test_t test = conn->cfg.test;
284
285 if (test == SOCK_TEST_TYPE_BI)
286 (void) sock_test_write (client_fd, conn->buf, rx_bytes, &conn->stats,
287 conn->cfg.verbose);
288
289 if (conn->stats.rx_bytes >= conn->cfg.total_bytes)
290 {
291 clock_gettime (CLOCK_REALTIME, &conn->stats.stop);
292 }
293}
294
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500295#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
296static inline void
297af_unix_echo (void)
298{
299 sock_server_main_t *ssm = &sock_server_main;
300 int af_unix_client_fd;
301 int rv;
302 int errno_val;
303 uint8_t buffer[256];
304 size_t nbytes = strlen (SOCK_TEST_MIXED_EPOLL_DATA) + 1;
305
306#if HAVE_ACCEPT4
307 af_unix_client_fd = accept4 (ssm->af_unix_listen_fd,
308 (struct sockaddr *) NULL, NULL, NULL);
309#else
310 af_unix_client_fd = accept (ssm->af_unix_listen_fd,
311 (struct sockaddr *) NULL, NULL);
312#endif
313 if (af_unix_client_fd < 0)
314 {
315 errno_val = errno;
316 perror ("ERROR in af_unix_accept()");
317 fprintf (stderr, "SERVER: ERROR: accept failed "
318 "(errno = %d)!\n", errno_val);
319 return;
320 }
321
322 printf ("SERVER: Got an AF_UNIX connection -- fd = %d (0x%08x)!\n",
323 af_unix_client_fd, af_unix_client_fd);
324
325 memset (buffer, 0, sizeof (buffer));
326
327 rv = read (af_unix_client_fd, buffer, nbytes);
328 if (rv < 0)
329 {
330 errno_val = errno;
331 perror ("ERROR in af_unix_echo(): read() failed");
332 fprintf (stderr, "SERVER: ERROR: read(af_unix_client_fd %d (0x%x), "
333 "\"%s\", nbytes %lu) failed (errno = %d)!\n",
334 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
335 errno_val);
336 goto done;
337 }
338
339 printf ("SERVER (AF_UNIX): RX (%d bytes) - '%s'\n", rv, buffer);
340
341 if (!strncmp (SOCK_TEST_MIXED_EPOLL_DATA, (const char *) buffer, nbytes))
342 {
343 rv = write (af_unix_client_fd, buffer, nbytes);
344 if (rv < 0)
345 {
346 errno_val = errno;
347 perror ("ERROR in af_unix_echo(): write() failed");
348 fprintf (stderr,
349 "SERVER: ERROR: write(af_unix_client_fd %d (0x%x), "
350 "\"%s\", nbytes %ld) failed (errno = %d)!\n",
351 af_unix_client_fd, af_unix_client_fd, buffer, nbytes,
352 errno_val);
353 goto done;
354 }
355 printf ("SERVER (AF_UNIX): TX (%d bytes) - '%s'\n", rv, buffer);
356 ssm->af_unix_xacts++;
357 }
358done:
359 close (af_unix_client_fd);
360}
361
362#endif
363
Dave Wallace543852a2017-08-03 02:11:34 -0400364static inline void
365new_client (void)
366{
367 sock_server_main_t *ssm = &sock_server_main;
368 int client_fd;
369 sock_server_conn_t *conn;
370
371 if (ssm->conn_pool_size < (ssm->num_conn + SOCK_SERVER_MAX_TEST_CONN + 1))
372 conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
373
374 conn = conn_pool_alloc ();
375 if (!conn)
376 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500377 fprintf (stderr, "\nSERVER: ERROR: No free connections!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400378 return;
379 }
380
381#ifdef VCL_TEST
Dave Wallace048b1d62018-01-03 22:24:41 -0500382 client_fd = vppcom_session_accept (ssm->listen_fd, &conn->endpt, 0);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400383 if (client_fd < 0)
384 errno = -client_fd;
Dave Wallace59179392017-11-07 02:20:07 -0500385#elif HAVE_ACCEPT4
386 client_fd = accept4 (ssm->listen_fd, (struct sockaddr *) NULL, NULL, NULL);
Dave Wallace543852a2017-08-03 02:11:34 -0400387#else
388 client_fd = accept (ssm->listen_fd, (struct sockaddr *) NULL, NULL);
389#endif
390 if (client_fd < 0)
391 {
392 int errno_val;
393 errno_val = errno;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400394 perror ("ERROR in new_client()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500395 fprintf (stderr, "SERVER: ERROR: accept failed "
396 "(errno = %d)!\n", errno_val);
Dave Wallaceee45d412017-11-24 21:44:06 -0500397 return;
Dave Wallace543852a2017-08-03 02:11:34 -0400398 }
399
400 printf ("SERVER: Got a connection -- fd = %d (0x%08x)!\n",
401 client_fd, client_fd);
402
403 conn->fd = client_fd;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400404
405#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400406 conn_fdset_set (conn, &ssm->rd_fdset);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400407 ssm->nfds++;
408#else
409 {
410 struct epoll_event ev;
411 int rv;
412
413 ev.events = EPOLLIN;
414 ev.data.u64 = conn - ssm->conn_pool;
415#ifdef VCL_TEST
416 rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
417 if (rv)
418 errno = -rv;
419#else
420 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, client_fd, &ev);
421#endif
422 if (rv < 0)
423 {
424 int errno_val;
425 errno_val = errno;
426 perror ("ERROR in new_client()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500427 fprintf (stderr, "SERVER: ERROR: epoll_ctl failed (errno = %d)!\n",
Dave Wallacef7f809c2017-10-03 01:48:42 -0400428 errno_val);
429 }
430 else
431 ssm->nfds++;
432 }
433#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400434}
435
436int
437main (int argc, char **argv)
438{
439 sock_server_main_t *ssm = &sock_server_main;
440 int client_fd, rv, main_rv = 0;
441 int tx_bytes, rx_bytes, nbytes;
442 sock_server_conn_t *conn;
443 sock_test_cfg_t *rx_cfg;
444 uint32_t xtra = 0;
445 uint64_t xtra_bytes = 0;
446 struct sockaddr_in servaddr;
447 int errno_val;
448 int v, i;
449 uint16_t port = SOCK_TEST_SERVER_PORT;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400450#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400451 fd_set _rfdset, *rfdset = &_rfdset;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400452#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400453#ifdef VCL_TEST
454 vppcom_endpt_t endpt;
455#else
Dave Wallacef7f809c2017-10-03 01:48:42 -0400456#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400457 fd_set _wfdset, *wfdset = &_wfdset;
458#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -0400459#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400460
461 if ((argc == 2) && (sscanf (argv[1], "%d", &v) == 1))
462 port = (uint16_t) v;
463
464 conn_pool_expand (SOCK_SERVER_MAX_TEST_CONN + 1);
465
466#ifdef VCL_TEST
467 rv = vppcom_app_create ("vcl_test_server");
468 if (rv)
469 {
470 errno = -rv;
471 ssm->listen_fd = -1;
472 }
473 else
474 {
475 ssm->listen_fd =
Dave Wallacec04cbf12018-02-07 18:14:02 -0500476 vppcom_session_create (VPPCOM_PROTO_TCP, 0 /* is_nonblocking */ );
Dave Wallace543852a2017-08-03 02:11:34 -0400477 }
478#else
479 ssm->listen_fd = socket (AF_INET, SOCK_STREAM, 0);
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500480#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
481 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
482 ssm->af_unix_listen_fd = socket (AF_UNIX, SOCK_STREAM, 0);
483 if (ssm->af_unix_listen_fd < 0)
484 {
485 errno_val = errno;
486 perror ("ERROR in main(): socket(AF_UNIX) failed");
487 fprintf (stderr,
488 "SERVER: ERROR: socket(AF_UNIX, SOCK_STREAM, 0) failed "
489 "(errno = %d)!\n", errno_val);
490 return ssm->af_unix_listen_fd;
491 }
492
493 memset (&ssm->serveraddr, 0, sizeof (ssm->serveraddr));
494 ssm->serveraddr.sun_family = AF_UNIX;
495 strcpy (ssm->serveraddr.sun_path, SOCK_TEST_AF_UNIX_FILENAME);
496
497 rv = bind (ssm->af_unix_listen_fd, (struct sockaddr *) &ssm->serveraddr,
498 SUN_LEN (&ssm->serveraddr));
499 if (rv < 0)
500 {
501 errno_val = errno;
502 perror ("ERROR in main(): bind(SOCK_TEST_AF_UNIX_FILENAME) failed");
503 fprintf (stderr, "SERVER: ERROR: bind() fd %d, \"%s\": "
504 "failed (errno = %d)!\n", ssm->af_unix_listen_fd,
505 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
506 close (ssm->af_unix_listen_fd);
507 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
508 return rv;
509 }
510
511 rv = listen (ssm->af_unix_listen_fd, 10);
512 if (rv < 0)
513 {
514 errno_val = errno;
515 perror ("ERROR in main(): listen(AF_UNIX) failed");
516 fprintf (stderr, "SERVER: ERROR: listen() fd %d, \"%s\": "
517 "failed (errno = %d)!\n", ssm->af_unix_listen_fd,
518 SOCK_TEST_AF_UNIX_FILENAME, errno_val);
519 close (ssm->af_unix_listen_fd);
520 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
521 return rv;
522 }
523#endif /* SOCK_SERVER_USE_EPOLL */
Dave Wallace543852a2017-08-03 02:11:34 -0400524#endif
525 if (ssm->listen_fd < 0)
526 {
527 errno_val = errno;
528 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500529 fprintf (stderr, "SERVER: ERROR: socket() failed "
530 "(errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400531 return ssm->listen_fd;
532 }
533
534 memset (&servaddr, 0, sizeof (servaddr));
535
536 servaddr.sin_family = AF_INET;
Dave Wallace33e002b2017-09-06 01:20:02 -0400537 servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
Dave Wallace543852a2017-08-03 02:11:34 -0400538 servaddr.sin_port = htons (port);
539
540#ifdef VCL_TEST
Dave Wallace543852a2017-08-03 02:11:34 -0400541 endpt.is_ip4 = (servaddr.sin_family == AF_INET);
542 endpt.ip = (uint8_t *) & servaddr.sin_addr;
543 endpt.port = (uint16_t) servaddr.sin_port;
544
545 rv = vppcom_session_bind (ssm->listen_fd, &endpt);
546 if (rv)
547 {
548 errno = -rv;
549 rv = -1;
550 }
551#else
552 rv =
553 bind (ssm->listen_fd, (struct sockaddr *) &servaddr, sizeof (servaddr));
554#endif
555 if (rv < 0)
556 {
557 errno_val = errno;
558 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500559 fprintf (stderr, "SERVER: ERROR: bind failed (errno = %d)!\n",
560 errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400561 return rv;
562 }
563
564#ifdef VCL_TEST
565 rv = vppcom_session_listen (ssm->listen_fd, 10);
566 if (rv)
567 {
568 errno = -rv;
569 rv = -1;
570 }
571#else
572 rv = listen (ssm->listen_fd, 10);
573#endif
574 if (rv < 0)
575 {
576 errno_val = errno;
577 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500578 fprintf (stderr, "SERVER: ERROR: listen failed "
579 "(errno = %d)!\n", errno_val);
Dave Wallace543852a2017-08-03 02:11:34 -0400580 return rv;
581 }
582
Dave Wallacef7f809c2017-10-03 01:48:42 -0400583#if ! SOCK_SERVER_USE_EPOLL
584
Dave Wallace543852a2017-08-03 02:11:34 -0400585 FD_ZERO (&ssm->wr_fdset);
586 FD_ZERO (&ssm->rd_fdset);
587
588 FD_SET (ssm->listen_fd, &ssm->rd_fdset);
589 ssm->nfds = ssm->listen_fd + 1;
590
Dave Wallacef7f809c2017-10-03 01:48:42 -0400591#else
592#ifdef VCL_TEST
593 ssm->epfd = vppcom_epoll_create ();
594 if (ssm->epfd < 0)
595 errno = -ssm->epfd;
596#else
597 ssm->epfd = epoll_create (1);
598#endif
599 if (ssm->epfd < 0)
600 {
601 errno_val = errno;
602 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500603 fprintf (stderr, "SERVER: ERROR: epoll_create failed (errno = %d)!\n",
Dave Wallacef7f809c2017-10-03 01:48:42 -0400604 errno_val);
605 return ssm->epfd;
606 }
607
608 ssm->listen_ev.events = EPOLLIN;
609 ssm->listen_ev.data.u32 = ~0;
610#ifdef VCL_TEST
611 rv = vppcom_epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd,
612 &ssm->listen_ev);
613 if (rv < 0)
614 errno = -rv;
615#else
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500616 ssm->af_unix_listen_ev.events = EPOLLIN;
617 ssm->af_unix_listen_ev.data.u32 = SOCK_TEST_AF_UNIX_ACCEPT_DATA;
618 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->af_unix_listen_fd,
619 &ssm->af_unix_listen_ev);
620 if (rv < 0)
621 {
622 errno_val = errno;
623 perror ("ERROR in main(): mixed epoll_ctl(EPOLL_CTL_ADD)");
624 fprintf (stderr, "SERVER: ERROR: mixed epoll_ctl(epfd %d (0x%x), "
625 "EPOLL_CTL_ADD, af_unix_listen_fd %d (0x%x), EPOLLIN) failed "
626 "(errno = %d)!\n", ssm->epfd, ssm->epfd,
627 ssm->af_unix_listen_fd, ssm->af_unix_listen_fd, errno_val);
628 close (ssm->af_unix_listen_fd);
629 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
630 return rv;
631 }
632
Dave Wallacef7f809c2017-10-03 01:48:42 -0400633 rv = epoll_ctl (ssm->epfd, EPOLL_CTL_ADD, ssm->listen_fd, &ssm->listen_ev);
634#endif
635 if (rv < 0)
636 {
637 errno_val = errno;
638 perror ("ERROR in main()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500639 fprintf (stderr, "SERVER: ERROR: epoll_ctl failed "
640 "(errno = %d)!\n", errno_val);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400641 return rv;
642 }
643#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400644
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500645 printf ("\nSERVER: Waiting for a client to connect on port %d...\n", port);
646
Dave Wallace543852a2017-08-03 02:11:34 -0400647 while (1)
648 {
Dave Wallacef7f809c2017-10-03 01:48:42 -0400649#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400650 _rfdset = ssm->rd_fdset;
651
652#ifdef VCL_TEST
653 rv = vppcom_select (ssm->nfds, (uint64_t *) rfdset, NULL, NULL, 0);
654#else
655 {
656 struct timeval timeout;
657 timeout = ssm->timeout;
658 _wfdset = ssm->wr_fdset;
659 rv = select (ssm->nfds, rfdset, wfdset, NULL, &timeout);
660 }
661#endif
662 if (rv < 0)
663 {
664 perror ("select()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500665 fprintf (stderr, "\nSERVER: ERROR: select() failed -- aborting!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400666 main_rv = -1;
667 goto done;
668 }
669 else if (rv == 0)
670 continue;
671
672 if (FD_ISSET (ssm->listen_fd, rfdset))
673 new_client ();
674
675 for (i = 0; i < ssm->conn_pool_size; i++)
676 {
677 if (!ssm->conn_pool[i].is_alloc)
678 continue;
679
680 conn = &ssm->conn_pool[i];
Dave Wallacef7f809c2017-10-03 01:48:42 -0400681#else
682 int num_ev;
683#ifdef VCL_TEST
684 num_ev = vppcom_epoll_wait (ssm->epfd, ssm->wait_events,
685 SOCK_SERVER_MAX_EPOLL_EVENTS, 60.0);
Dave Wallace0fd6ad62017-10-20 13:23:40 -0400686 if (num_ev < 0)
687 errno = -num_ev;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400688#else
689 num_ev = epoll_wait (ssm->epfd, ssm->wait_events,
690 SOCK_SERVER_MAX_EPOLL_EVENTS, 60000);
691#endif
692 if (num_ev < 0)
693 {
694 perror ("epoll_wait()");
Dave Wallace048b1d62018-01-03 22:24:41 -0500695 fprintf (stderr, "\nSERVER: ERROR: epoll_wait() "
696 "failed -- aborting!\n");
Dave Wallacef7f809c2017-10-03 01:48:42 -0400697 main_rv = -1;
698 goto done;
699 }
700 if (num_ev == 0)
701 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500702 fprintf (stderr, "\nSERVER: epoll_wait() timeout!\n");
Dave Wallacef7f809c2017-10-03 01:48:42 -0400703 continue;
704 }
705 for (i = 0; i < num_ev; i++)
706 {
Dave Wallace63f18592018-03-13 19:37:54 -0400707 conn = &ssm->conn_pool[ssm->wait_events[i].data.u32];
708 if (ssm->wait_events[i].events & (EPOLLHUP | EPOLLRDHUP))
709 {
710#ifdef VCL_TEST
711 vppcom_session_close (conn->fd);
712#else
713 close (conn->fd);
714#endif
715 continue;
716 }
Dave Wallacef7f809c2017-10-03 01:48:42 -0400717 if (ssm->wait_events[i].data.u32 == ~0)
718 {
719 new_client ();
720 continue;
721 }
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500722#if !defined (VCL_TEST)
723 else if (ssm->wait_events[i].data.u32 ==
724 SOCK_TEST_AF_UNIX_ACCEPT_DATA)
725 {
726 af_unix_echo ();
727 continue;
728 }
729#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -0400730#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400731 client_fd = conn->fd;
732
Dave Wallacef7f809c2017-10-03 01:48:42 -0400733#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400734 if (FD_ISSET (client_fd, rfdset))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400735#else
736 if (EPOLLIN & ssm->wait_events[i].events)
737#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400738 {
739 rx_bytes = sock_test_read (client_fd, conn->buf,
740 conn->buf_size, &conn->stats);
741 if (rx_bytes > 0)
742 {
743 rx_cfg = (sock_test_cfg_t *) conn->buf;
744 if (rx_cfg->magic == SOCK_TEST_CFG_CTRL_MAGIC)
745 {
746 if (rx_cfg->verbose)
747 {
748 printf ("SERVER (fd %d): Received a cfg message!\n",
749 client_fd);
750 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
751 }
752
753 if (rx_bytes != sizeof (*rx_cfg))
754 {
755 printf ("SERVER (fd %d): Invalid cfg message "
756 "size (%d)!\n Should be %lu bytes.\n",
757 client_fd, rx_bytes, sizeof (*rx_cfg));
758 conn->cfg.rxbuf_size = 0;
759 conn->cfg.num_writes = 0;
760 if (conn->cfg.verbose)
761 {
762 printf ("SERVER (fd %d): Replying to "
763 "cfg message!\n", client_fd);
764 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
765 }
766 sock_test_write (client_fd, (uint8_t *) & conn->cfg,
767 sizeof (conn->cfg), NULL,
768 conn->cfg.verbose);
769 continue;
770 }
771
772 switch (rx_cfg->test)
773 {
774 case SOCK_TEST_TYPE_NONE:
775 case SOCK_TEST_TYPE_ECHO:
776 sync_config_and_reply (conn, rx_cfg);
777 break;
778
779 case SOCK_TEST_TYPE_BI:
780 case SOCK_TEST_TYPE_UNI:
781 stream_test_server_start_stop (conn, rx_cfg);
782 break;
783
784 case SOCK_TEST_TYPE_EXIT:
785 printf ("SERVER: Have a great day, "
786 "connection %d!\n", client_fd);
787#ifdef VCL_TEST
788 vppcom_session_close (client_fd);
789#else
790 close (client_fd);
791#endif
792 conn_pool_free (conn);
Dave Wallaceee45d412017-11-24 21:44:06 -0500793 printf ("SERVER: Closed client fd %d\n", client_fd);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400794#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400795 if (ssm->nfds == (ssm->listen_fd + 1))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400796#else
797 ssm->nfds--;
798 if (!ssm->nfds)
799#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400800 {
801 printf ("SERVER: All client connections "
802 "closed.\n\nSERVER: "
803 "May the force be with you!\n\n");
804 goto done;
805 }
806 break;
807
808 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500809 fprintf (stderr,
810 "SERVER: ERROR: Unknown test type!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400811 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
812 break;
813 }
814 continue;
815 }
816
817 else if ((conn->cfg.test == SOCK_TEST_TYPE_UNI) ||
818 (conn->cfg.test == SOCK_TEST_TYPE_BI))
819 {
820 stream_test_server (conn, rx_bytes);
821 continue;
822 }
823
Chris Luke879ace32017-09-26 13:15:16 -0400824 else if (isascii (conn->buf[0]))
Chris Lukeab7b8d92017-09-07 07:40:13 -0400825 {
826 // If it looks vaguely like a string, make sure it's terminated
827 ((char *) conn->buf)[rx_bytes <
828 conn->buf_size ? rx_bytes :
829 conn->buf_size - 1] = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400830 printf ("SERVER (fd %d): RX (%d bytes) - '%s'\n",
Chris Lukeab7b8d92017-09-07 07:40:13 -0400831 conn->fd, rx_bytes, conn->buf);
832 }
Dave Wallace543852a2017-08-03 02:11:34 -0400833 }
834 else // rx_bytes < 0
835 {
836 if (errno == ECONNRESET)
837 {
838 printf ("\nSERVER: Connection reset by remote peer.\n"
839 " Y'all have a great day now!\n\n");
840 break;
841 }
842 else
843 continue;
844 }
845
Chris Luke879ace32017-09-26 13:15:16 -0400846 if (isascii (conn->buf[0]))
Dave Wallace543852a2017-08-03 02:11:34 -0400847 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500848 /* If it looks vaguely like a string,
849 * make sure it's terminated
850 */
Chris Luke879ace32017-09-26 13:15:16 -0400851 ((char *) conn->buf)[rx_bytes <
852 conn->buf_size ? rx_bytes :
853 conn->buf_size - 1] = 0;
Dave Wallace543852a2017-08-03 02:11:34 -0400854 if (xtra)
Dave Wallace048b1d62018-01-03 22:24:41 -0500855 fprintf (stderr, "SERVER: ERROR: "
856 "FIFO not drained in previous test!\n"
Dave Wallace543852a2017-08-03 02:11:34 -0400857 " extra chunks %u (0x%x)\n"
858 " extra bytes %lu (0x%lx)\n",
859 xtra, xtra, xtra_bytes, xtra_bytes);
860
861 xtra = 0;
862 xtra_bytes = 0;
863
864 if (conn->cfg.verbose)
865 printf ("SERVER (fd %d): Echoing back\n", client_fd);
866
867 nbytes = strlen ((const char *) conn->buf) + 1;
868
869 tx_bytes = sock_test_write (client_fd, conn->buf,
870 nbytes, &conn->stats,
871 conn->cfg.verbose);
872 if (tx_bytes >= 0)
873 printf ("SERVER (fd %d): TX (%d bytes) - '%s'\n",
874 conn->fd, tx_bytes, conn->buf);
875 }
876
877 else // Extraneous read data from non-echo tests???
878 {
879 xtra++;
880 xtra_bytes += rx_bytes;
881 }
882 }
883 }
884 }
885
886done:
887#ifdef VCL_TEST
888 vppcom_session_close (ssm->listen_fd);
889 vppcom_app_destroy ();
890#else
891 close (ssm->listen_fd);
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500892
893#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
894 close (ssm->af_unix_listen_fd);
895 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
896#endif /* SOCK_SERVER_USE_EPOLL */
897
Dave Wallace543852a2017-08-03 02:11:34 -0400898#endif
899 if (ssm->conn_pool)
900 free (ssm->conn_pool);
901
902 return main_rv;
903}
904
905/*
906 * fd.io coding-style-patch-verification: ON
907 *
908 * Local Variables:
909 * eval: (c-set-style "gnu")
910 * End:
911 */