summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/lib/roken/test-mini_inetd.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/roken/test-mini_inetd.c')
-rw-r--r--third_party/heimdal/lib/roken/test-mini_inetd.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/roken/test-mini_inetd.c b/third_party/heimdal/lib/roken/test-mini_inetd.c
new file mode 100644
index 0000000..7ab996a
--- /dev/null
+++ b/third_party/heimdal/lib/roken/test-mini_inetd.c
@@ -0,0 +1,371 @@
+/***********************************************************************
+ * Copyright (c) 2009, Secure Endpoints Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+#include <config.h>
+#include <roken.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define PORT 8013
+#define PORT_S "8013"
+
+char * prog = "Master";
+int is_client = 0;
+
+static int
+get_address(int flags, struct addrinfo ** ret)
+{
+ struct addrinfo ai;
+ int rv;
+
+ memset(&ai, 0, sizeof(ai));
+
+ ai.ai_flags = flags | AI_NUMERICHOST;
+ ai.ai_family = AF_INET;
+ ai.ai_socktype = SOCK_STREAM;
+ ai.ai_protocol = PF_UNSPEC;
+
+ rv = getaddrinfo("127.0.0.1", PORT_S, &ai, ret);
+ if (rv)
+ warnx("getaddrinfo: %s", gai_strerror(rv));
+ return rv;
+}
+
+static int
+get_connected_socket(rk_socket_t * s_ret)
+{
+ struct addrinfo * ai = NULL;
+ int rv = 0;
+ rk_socket_t s = rk_INVALID_SOCKET;
+
+ rv = get_address(0, &ai);
+ if (rv)
+ return rv;
+
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (rk_IS_BAD_SOCKET(s)) {
+ rv = 1;
+ goto done;
+ }
+
+ rv = connect(s, ai->ai_addr, ai->ai_addrlen);
+ if (rk_IS_SOCKET_ERROR(rv))
+ goto done;
+
+ *s_ret = s;
+ s = rk_INVALID_SOCKET;
+ rv = 0;
+
+ done:
+ if (!rk_IS_BAD_SOCKET(s))
+ rk_closesocket(s);
+
+ if (ai)
+ freeaddrinfo(ai);
+
+ return (rv) ? rk_SOCK_ERRNO : 0;
+}
+
+const char * test_strings[] = {
+ "Hello",
+ "01234566789012345689012345678901234567890123456789",
+ "Another test",
+ "exit"
+};
+
+static int
+test_simple_echo_client(void)
+{
+ rk_socket_t s = rk_INVALID_SOCKET;
+ int rv;
+ char buf[81];
+ int i;
+
+ fprintf(stderr, "[%s] Getting connected socket...", getprogname());
+ rv = get_connected_socket(&s);
+ if (rv) {
+ fprintf(stderr, "\n[%s] get_connected_socket() failed (%s)\n",
+ getprogname(), strerror(rk_SOCK_ERRNO));
+ return 1;
+ }
+
+ fprintf(stderr, "[%s] done\n", getprogname());
+
+ for (i=0; i < sizeof(test_strings)/sizeof(test_strings[0]); i++) {
+ rv = send(s, test_strings[i], strlen(test_strings[i]), 0);
+ if (rk_IS_SOCKET_ERROR(rv)) {
+ fprintf(stderr, "[%s] send() failure (%s)\n",
+ getprogname(), strerror(rk_SOCK_ERRNO));
+ rk_closesocket(s);
+ return 1;
+ }
+
+ rv = recv(s, buf, sizeof(buf), 0);
+ if (rk_IS_SOCKET_ERROR(rv)) {
+ fprintf (stderr, "[%s] recv() failure (%s)\n",
+ getprogname(), strerror(rk_SOCK_ERRNO));
+ rk_closesocket(s);
+ return 1;
+ }
+
+ if (rv == 0) {
+ fprintf (stderr, "[%s] No data received\n", prog);
+ rk_closesocket(s);
+ return 1;
+ }
+
+ if (rv != strlen(test_strings[i])) {
+ fprintf (stderr, "[%s] Data length mismatch %d != %zu\n", prog, rv, strlen(test_strings[i]));
+ rk_closesocket(s);
+ return 1;
+ }
+ }
+
+ fprintf (stderr, "[%s] Done\n", prog);
+ rk_closesocket(s);
+ return 0;
+}
+
+static int
+test_simple_echo_socket(void)
+{
+ fprintf (stderr, "[%s] Process ID %d\n", prog, GetCurrentProcessId());
+ fprintf (stderr, "[%s] Starting echo test with sockets\n", prog);
+
+ if (is_client) {
+ return test_simple_echo_client();
+ } else {
+
+ rk_socket_t s = rk_INVALID_SOCKET;
+
+ fprintf (stderr, "[%s] Listening for connections...\n", prog);
+ mini_inetd(htons(PORT), &s);
+ if (rk_IS_BAD_SOCKET(s)) {
+ fprintf (stderr, "[%s] Connect failed (%s)\n",
+ getprogname(), strerror(rk_SOCK_ERRNO));
+ } else {
+ fprintf (stderr, "[%s] Connected\n", prog);
+ }
+
+ {
+ char buf[81];
+ int rv, srv;
+
+ while ((rv = recv(s, buf, sizeof(buf), 0)) != 0 && !rk_IS_SOCKET_ERROR(rv)) {
+ buf[rv] = 0;
+ fprintf(stderr, "[%s] Received [%s]\n", prog, buf);
+
+ /* simple echo */
+ srv = send(s, buf, rv, 0);
+ if (srv != rv) {
+ if (rk_IS_SOCKET_ERROR(srv))
+ fprintf(stderr, "[%s] send() error [%s]\n",
+ getprogname(), strerror(rk_SOCK_ERRNO));
+ else
+ fprintf(stderr, "[%s] send() size mismatch %d != %d",
+ getprogname(), srv, rv);
+ }
+
+ if (strcmp(buf, "exit") == 0) {
+ fprintf(stderr, "[%s] Exiting...\n", prog);
+ shutdown(s, SD_SEND);
+ rk_closesocket(s);
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "[%s] recv() failed (%s)\n",
+ getprogname(),
+ strerror(rk_SOCK_ERRNO));
+ }
+
+ rk_closesocket(s);
+ }
+
+ return 1;
+}
+
+static int
+test_simple_echo(void)
+{
+ fprintf (stderr, "[%s] Starting echo test\n", prog);
+
+ if (is_client) {
+
+ return test_simple_echo_client();
+
+ } else {
+
+ fprintf (stderr, "[%s] Listening for connections...\n", prog);
+ mini_inetd(htons(PORT), NULL);
+ fprintf (stderr, "[%s] Connected\n", prog);
+
+ {
+ char buf[81];
+ while (gets(buf)) {
+ fprintf(stderr, "[%s] Received [%s]\n", prog, buf);
+
+ if (strcmp(buf, "exit") == 0)
+ return 0;
+
+ /* simple echo */
+ puts(buf);
+ }
+
+ fprintf(stderr, "[%s] gets() failed (%s)\n", prog, _strerror("gets"));
+ }
+ }
+
+ return 1;
+}
+
+static int
+do_client(void)
+{
+ int rv = 0;
+
+ if (rk_SOCK_INIT())
+ errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO));
+
+ prog = "Client";
+ is_client = 1;
+
+ fprintf(stderr, "Starting client...\n");
+
+ rv = test_simple_echo_socket();
+
+ rk_SOCK_EXIT();
+
+ return rv;
+}
+
+static int
+do_server(void)
+{
+ int rv = 0;
+
+ if (rk_SOCK_INIT())
+ errx(1, "Failed to initialize sockets (%s)", strerror(rk_SOCK_ERRNO));
+
+ prog = "Server";
+
+ fprintf(stderr, "Starting server...\n");
+
+ rv = test_simple_echo_socket();
+
+ rk_SOCK_EXIT();
+
+ return rv;
+}
+
+static time_t
+wait_callback(void *p)
+{
+ return (time_t)-1;
+}
+
+static int
+do_test(char * path)
+{
+ intptr_t p_server;
+ intptr_t p_client;
+ int client_rv;
+ int server_rv;
+
+ p_server = _spawnl(_P_NOWAIT, path, path, "--server", NULL);
+ if (p_server <= 0) {
+ fprintf(stderr, "%s: %s", path, _strerror("Can't start server process"));
+ return 1;
+ }
+#ifdef _WIN32
+ /* On Windows, the _spawn*() functions return a process handle on
+ success. We need a process ID for use with
+ wait_for_process_timed(). */
+
+ p_server = GetProcessId((HANDLE) p_server);
+#endif
+ fprintf(stderr, "Created server process ID %d\n", p_server);
+
+ p_client = _spawnl(_P_NOWAIT, path, path, "--client", NULL);
+ if (p_client <= 0) {
+ fprintf(stderr, "%s: %s", path, _strerror("Can't start client process"));
+ fprintf(stderr, "Waiting for server process to terminate ...");
+ wait_for_process_timed(p_server, wait_callback, NULL, 5);
+ fprintf(stderr, "DONE\n");
+ return 1;
+ }
+#ifdef _WIN32
+ p_client = GetProcessId((HANDLE) p_client);
+#endif
+ fprintf(stderr, "Created client process ID %d\n", p_client);
+
+ fprintf(stderr, "Waiting for client process to terminate ...");
+ client_rv = wait_for_process_timed(p_client, wait_callback, NULL, 5);
+ if (SE_IS_ERROR(client_rv)) {
+ fprintf(stderr, "\nwait_for_process_timed() failed for client. rv=%d\n", client_rv);
+ } else {
+ fprintf(stderr, "DONE\n");
+ }
+
+ fprintf(stderr, "Waiting for server process to terminate ...");
+ server_rv = wait_for_process_timed(p_server, wait_callback, NULL, 5);
+ if (SE_IS_ERROR(server_rv)) {
+ fprintf(stderr, "\nwait_for_process_timed() failed for server. rv=%d\n", server_rv);
+ } else {
+ fprintf(stderr, "DONE\n");
+ }
+
+ if (client_rv == 0 && server_rv == 0) {
+ fprintf(stderr, "PASS\n");
+ return 0;
+ } else {
+ fprintf(stderr, "FAIL: Client rv=%d, Server rv=%d\n", client_rv, server_rv);
+ return 1;
+ }
+}
+
+int main(int argc, char ** argv)
+{
+ setprogname(argv[0]);
+
+ if (argc == 2 && strcmp(argv[1], "--client") == 0)
+ return do_client();
+ else if (argc == 2 && strcmp(argv[1], "--server") == 0)
+ return do_server();
+ else if (argc == 1)
+ return do_test(argv[0]);
+ else {
+ printf ("%s: Test mini_inetd() function. Run with no arguments to start test\n",
+ argv[0]);
+ return 1;
+ }
+}