From 85563afeac954a50de7e4c207f43b57a4e63e474 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 12 Jun 2019 19:23:39 +0300 Subject: More tests for built-in services * tests/builtin.at: Check tcpmux services. * tests/nt.c: Add tcpmux support, improve error checking. * tests/chargen.c: Improve error checking. --- tests/builtin.at | 77 +++++++++++++++++++++++++++++ tests/chargen.c | 11 ++++- tests/nt.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 211 insertions(+), 22 deletions(-) diff --git a/tests/builtin.at b/tests/builtin.at index 40f65fa..893f213 100644 --- a/tests/builtin.at +++ b/tests/builtin.at @@ -129,3 +129,80 @@ to the input. m4_popdef([IT_BUILTIN]) m4_popdef([IT_SPECIAL]) + +# IT_TCPMUX([KW],[ID],[INPUT],[OUTPUT]) +m4_define([IT_TCPMUX], +[AT_SETUP([tcpmux: $1]) +AT_KEYWORDS([inetd builtin internal tcpmux $1]) +AT_CHECK([ +PIES_XFAIL_CHECK +PIES_CONTROL_INIT +: ${PIES_TEST_INET_SOCKET:=unix://$PWD/in.sock} +m4_if([$3],[],[],[AT_DATA([input],[$3])]) +cat > pies.conf <<_EOT +component master { + socket "$PIES_TEST_INET_SOCKET"; + service tcpmux; + flags internal; +} +component one { + service one; + flags (tcpmuxplus); + tcpmux-master master; + command "$auxdir/in.test $PWD/one.log"; + stderr file "$PWD/one.err"; +} +component two { + service two; + flags (tcpmuxplus); + tcpmux-master master; + command "$auxdir/in.test $PWD/two.log"; + stderr file "$PWD/two.err"; +} +component test { + command "nt -t [$2]m4_if([$3],[],,[ -i $PWD/input]) -o $PWD/test.out '$PIES_TEST_INET_SOCKET'"; + stderr file "$PWD/test.err"; + return-code * { + action disable; + exec "piesctl --no-netrc --url=$PIES_CTLSOCK shutdown"; + } +} +_EOT + +set -e +to 10 \ + pies --foreground --stderr \ + --config-file control.conf --config-file pies.conf --debug 1 2>errlog + +for err in one.err two.err test.err +do + if test -s $err; then + echo "$err:" + cat $err + fi +done >&2 + +if test -f test.out; then + cat test.out | tr -d '\r' +fi +], +[0], +[$4]) +AT_CLEANUP +]) + +IT_TCPMUX([help],[help],[], +[one +two +]) + +IT_TCPMUX([service],[one], +[Test one +quit +], +[OK Test one +]) + +m4_popdef([IT_TCPMUX]) + + diff --git a/tests/chargen.c b/tests/chargen.c index a3b3290..75d096c 100644 --- a/tests/chargen.c +++ b/tests/chargen.c @@ -76,13 +76,20 @@ main (int argc, char **argv) if (pies_url_create (&url, argv[1])) { - perror (argv[0]); + perror (argv[1]); return 64; } fd = url_connect (url, NULL); + if (fd == -1) + return 1; fp = fdopen (fd, "r"); - + if (!fp) + { + perror ("fdopen"); + return 1; + } + first = next_char (0); c = first; do diff --git a/tests/nt.c b/tests/nt.c index 876ffb1..c7f4be7 100644 --- a/tests/nt.c +++ b/tests/nt.c @@ -136,7 +136,7 @@ netcat_stream_read (netcat_server_t *srv) if (errno == EINTR) return 0; grecs_error (NULL, errno, "%s: read", srv->id); - srv->pollfd->events &= ~POLLIN; + netcat_stream_disconnect (srv, POLLIN); return -1; } if (n == 0 || !peer_is_state (srv, POLLOUT)) @@ -185,11 +185,12 @@ netcat_stream_write (netcat_server_t *srv) if (errno == EINTR) return 0; grecs_error (NULL, errno, "%s: write", srv->id); + netcat_stream_disconnect (srv, POLLOUT); return -1; } if (n == 0) { - // FIXME: eof + netcat_stream_disconnect (srv, POLLOUT); return -1; } return 0; @@ -220,8 +221,99 @@ disconnect_stdout (netcat_server_t *srv) exit (0); } +void +fd_write (int fd, char const *str, size_t len) +{ + while (len) + { + ssize_t n = write (fd, str, len); + if (n == -1) + { + perror ("socket write"); + exit (1); + } + if (n == 0) + { + fprintf (stderr, "zero write\n"); + exit (1); + } + len -= n; + str += n; + } +} + +void +fd_writeln (int fd, char const *str) +{ + fd_write (fd, str, strlen (str)); + fd_write (fd, "\r\n", 2); +} + +int +fd_getc (int fd) +{ + char c; + ssize_t n = read (fd, &c, 1); + if (n == -1) + { + perror ("socket read"); + exit (1); + } + if (n == 0) + c = EOF; + return c; +} + +static void +tcpmux_init (int fd, char const *service) +{ + int c; + + fd_writeln (fd, service); + + if (strcmp (service, "help") == 0) + { + while ((c = fd_getc (fd)) != EOF) + { + fputc (c, stdout); + } + close (fd); + exit (0); + } + + c = fd_getc (fd); + if (c == 0) + { + fprintf (stderr, "socket read: unexpected eof\n"); + exit (1); + } + if (c == '+') + { + while ((c = fd_getc (fd)) != '\n') + { + if (c == EOF) + { + fprintf (stderr, "socket read: unexpected eof\n"); + exit (1); + } + } + } + else + { + fprintf (stderr, "service rejected: "); + do + { + if (c != '\r') + fputc (c, stderr); + } + while ((c = fd_getc (fd)) != 0 && c != '\n'); + fputc ('\n', stderr); + exit (1); + } +} + static int -netcat (char const *urlstr) +netcat (char const *urlstr, char const *tcpmux_service) { int fd; struct pies_url *url; @@ -239,6 +331,9 @@ netcat (char const *urlstr) if (fd == -1) return 1; + if (tcpmux_service) + tcpmux_init (fd, tcpmux_service); + pfd[0].fd = 0; pfd[0].events = 0; srvin = netcat_server_create ("stdin", &pfd[0], POLLIN, disconnect_stdin, NULL); @@ -265,25 +360,26 @@ netcat (char const *urlstr) for (srv = server_head; srv; ) { netcat_server_t *next = srv->next; - int events; - events = (srv->pollfd->events|POLLHUP) - & (srv->pollfd->revents - & (srv->state | ((srv->state & POLLOUT) ? POLLHUP : 0))); - if (events) + if ((srv->pollfd->revents & srv->state) & POLLIN) + netcat_stream_read (srv); + if ((srv->pollfd->revents & srv->state) & POLLOUT) + netcat_stream_write (srv); + if ((srv->state & POLLOUT) && (srv->pollfd->revents & POLLHUP)) { - if (events & POLLIN) - netcat_stream_read (srv); - if (events & POLLOUT) - netcat_stream_write (srv); - if (events & POLLHUP) + //grecs_error (NULL, 0, "HUP on %s", srv->id); + netcat_stream_disconnect (srv, srv->state); + } + if (srv->state == 0 || srv->pollfd->fd == -1) + { + netcat_server_t *peer = srv->peer; + if (peer && peer->pollfd->events == 0) { - //grecs_error (NULL, 0, "HUP on %s", srv->id); - netcat_stream_disconnect (srv, srv->state); + netcat_stream_disconnect (peer, peer->state); + netcat_server_remove (peer); } + netcat_server_remove (srv); } - if (srv->state == 0 || srv->pollfd->fd == -1) - netcat_server_remove (srv); srv = next; } } @@ -311,17 +407,22 @@ redirect (int sfd, char const *name) static void usage (FILE *fp) { - fprintf (fp, "usage: nt [-i IFILE] [-o OFILE] URL\n"); + fprintf (fp, "usage: nt [-i IFILE] [-o OFILE] [-t SERVICE] URL\n"); fprintf (fp, "Reads data from stdin (or IFILE) and sends them to URL.\n"); fprintf (fp, "Reads replies from URL and sends them to stdout (or OFILE).\n"); + fprintf (fp, "\nOPTIONS\n\n"); + fprintf (fp, " -t SERVICE use TCPMUX service\n"); + fprintf (fp, " -i IFILE read input from IFILE\n"); + fprintf (fp, " -o OFILE write output to OFILE\n"); } int main (int argc, char **argv) { int c; + char const *tcpmux_service = NULL; - while ((c = getopt (argc, argv, "i:o:")) != EOF) + while ((c = getopt (argc, argv, "i:o:t:")) != EOF) { switch (c) { @@ -333,6 +434,10 @@ main (int argc, char **argv) redirect (1, optarg); break; + case 't': + tcpmux_service = optarg; + break; + default: exit (64); } @@ -347,5 +452,5 @@ main (int argc, char **argv) exit (64); } - return netcat (argv[0]); + return netcat (argv[0], tcpmux_service); } -- cgit v1.2.1