blob: c0baefa99dea06d00fdbd584bfd47b545c4d33c0 [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 {
707 if (ssm->wait_events[i].data.u32 == ~0)
708 {
709 new_client ();
710 continue;
711 }
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500712#if !defined (VCL_TEST)
713 else if (ssm->wait_events[i].data.u32 ==
714 SOCK_TEST_AF_UNIX_ACCEPT_DATA)
715 {
716 af_unix_echo ();
717 continue;
718 }
719#endif
Dave Wallacef7f809c2017-10-03 01:48:42 -0400720 conn = &ssm->conn_pool[ssm->wait_events[i].data.u32];
721#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400722 client_fd = conn->fd;
723
Dave Wallacef7f809c2017-10-03 01:48:42 -0400724#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400725 if (FD_ISSET (client_fd, rfdset))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400726#else
727 if (EPOLLIN & ssm->wait_events[i].events)
728#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400729 {
730 rx_bytes = sock_test_read (client_fd, conn->buf,
731 conn->buf_size, &conn->stats);
732 if (rx_bytes > 0)
733 {
734 rx_cfg = (sock_test_cfg_t *) conn->buf;
735 if (rx_cfg->magic == SOCK_TEST_CFG_CTRL_MAGIC)
736 {
737 if (rx_cfg->verbose)
738 {
739 printf ("SERVER (fd %d): Received a cfg message!\n",
740 client_fd);
741 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
742 }
743
744 if (rx_bytes != sizeof (*rx_cfg))
745 {
746 printf ("SERVER (fd %d): Invalid cfg message "
747 "size (%d)!\n Should be %lu bytes.\n",
748 client_fd, rx_bytes, sizeof (*rx_cfg));
749 conn->cfg.rxbuf_size = 0;
750 conn->cfg.num_writes = 0;
751 if (conn->cfg.verbose)
752 {
753 printf ("SERVER (fd %d): Replying to "
754 "cfg message!\n", client_fd);
755 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
756 }
757 sock_test_write (client_fd, (uint8_t *) & conn->cfg,
758 sizeof (conn->cfg), NULL,
759 conn->cfg.verbose);
760 continue;
761 }
762
763 switch (rx_cfg->test)
764 {
765 case SOCK_TEST_TYPE_NONE:
766 case SOCK_TEST_TYPE_ECHO:
767 sync_config_and_reply (conn, rx_cfg);
768 break;
769
770 case SOCK_TEST_TYPE_BI:
771 case SOCK_TEST_TYPE_UNI:
772 stream_test_server_start_stop (conn, rx_cfg);
773 break;
774
775 case SOCK_TEST_TYPE_EXIT:
776 printf ("SERVER: Have a great day, "
777 "connection %d!\n", client_fd);
778#ifdef VCL_TEST
779 vppcom_session_close (client_fd);
780#else
781 close (client_fd);
782#endif
783 conn_pool_free (conn);
Dave Wallaceee45d412017-11-24 21:44:06 -0500784 printf ("SERVER: Closed client fd %d\n", client_fd);
Dave Wallacef7f809c2017-10-03 01:48:42 -0400785#if ! SOCK_SERVER_USE_EPOLL
Dave Wallace543852a2017-08-03 02:11:34 -0400786 if (ssm->nfds == (ssm->listen_fd + 1))
Dave Wallacef7f809c2017-10-03 01:48:42 -0400787#else
788 ssm->nfds--;
789 if (!ssm->nfds)
790#endif
Dave Wallace543852a2017-08-03 02:11:34 -0400791 {
792 printf ("SERVER: All client connections "
793 "closed.\n\nSERVER: "
794 "May the force be with you!\n\n");
795 goto done;
796 }
797 break;
798
799 default:
Dave Wallace048b1d62018-01-03 22:24:41 -0500800 fprintf (stderr,
801 "SERVER: ERROR: Unknown test type!\n");
Dave Wallace543852a2017-08-03 02:11:34 -0400802 sock_test_cfg_dump (rx_cfg, 0 /* is_client */ );
803 break;
804 }
805 continue;
806 }
807
808 else if ((conn->cfg.test == SOCK_TEST_TYPE_UNI) ||
809 (conn->cfg.test == SOCK_TEST_TYPE_BI))
810 {
811 stream_test_server (conn, rx_bytes);
812 continue;
813 }
814
Chris Luke879ace32017-09-26 13:15:16 -0400815 else if (isascii (conn->buf[0]))
Chris Lukeab7b8d92017-09-07 07:40:13 -0400816 {
817 // If it looks vaguely like a string, make sure it's terminated
818 ((char *) conn->buf)[rx_bytes <
819 conn->buf_size ? rx_bytes :
820 conn->buf_size - 1] = 0;
Dave Wallacef7f809c2017-10-03 01:48:42 -0400821 printf ("SERVER (fd %d): RX (%d bytes) - '%s'\n",
Chris Lukeab7b8d92017-09-07 07:40:13 -0400822 conn->fd, rx_bytes, conn->buf);
823 }
Dave Wallace543852a2017-08-03 02:11:34 -0400824 }
825 else // rx_bytes < 0
826 {
827 if (errno == ECONNRESET)
828 {
829 printf ("\nSERVER: Connection reset by remote peer.\n"
830 " Y'all have a great day now!\n\n");
831 break;
832 }
833 else
834 continue;
835 }
836
Chris Luke879ace32017-09-26 13:15:16 -0400837 if (isascii (conn->buf[0]))
Dave Wallace543852a2017-08-03 02:11:34 -0400838 {
Dave Wallace048b1d62018-01-03 22:24:41 -0500839 /* If it looks vaguely like a string,
840 * make sure it's terminated
841 */
Chris Luke879ace32017-09-26 13:15:16 -0400842 ((char *) conn->buf)[rx_bytes <
843 conn->buf_size ? rx_bytes :
844 conn->buf_size - 1] = 0;
Dave Wallace543852a2017-08-03 02:11:34 -0400845 if (xtra)
Dave Wallace048b1d62018-01-03 22:24:41 -0500846 fprintf (stderr, "SERVER: ERROR: "
847 "FIFO not drained in previous test!\n"
Dave Wallace543852a2017-08-03 02:11:34 -0400848 " extra chunks %u (0x%x)\n"
849 " extra bytes %lu (0x%lx)\n",
850 xtra, xtra, xtra_bytes, xtra_bytes);
851
852 xtra = 0;
853 xtra_bytes = 0;
854
855 if (conn->cfg.verbose)
856 printf ("SERVER (fd %d): Echoing back\n", client_fd);
857
858 nbytes = strlen ((const char *) conn->buf) + 1;
859
860 tx_bytes = sock_test_write (client_fd, conn->buf,
861 nbytes, &conn->stats,
862 conn->cfg.verbose);
863 if (tx_bytes >= 0)
864 printf ("SERVER (fd %d): TX (%d bytes) - '%s'\n",
865 conn->fd, tx_bytes, conn->buf);
866 }
867
868 else // Extraneous read data from non-echo tests???
869 {
870 xtra++;
871 xtra_bytes += rx_bytes;
872 }
873 }
874 }
875 }
876
877done:
878#ifdef VCL_TEST
879 vppcom_session_close (ssm->listen_fd);
880 vppcom_app_destroy ();
881#else
882 close (ssm->listen_fd);
Dave Wallace3ee1fe12018-02-23 01:09:11 -0500883
884#if SOCK_SERVER_USE_EPOLL && !defined (VCL_TEST)
885 close (ssm->af_unix_listen_fd);
886 unlink ((const char *) SOCK_TEST_AF_UNIX_FILENAME);
887#endif /* SOCK_SERVER_USE_EPOLL */
888
Dave Wallace543852a2017-08-03 02:11:34 -0400889#endif
890 if (ssm->conn_pool)
891 free (ssm->conn_pool);
892
893 return main_rv;
894}
895
896/*
897 * fd.io coding-style-patch-verification: ON
898 *
899 * Local Variables:
900 * eval: (c-set-style "gnu")
901 * End:
902 */