/* This thing checks select.c for basic functionality */

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "select.h"
#include "socket.h"

#define	TEST_STR "wwzzzoooooooooooooooooommmmm"

sockset_t *sockset;
int c = 0;


void
die(char *fmt, ...) {
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);

	exit(1);
}


/* server */

void
write_now(sock_t *sock, void *data) {
	if (write(sock->fd, TEST_STR, strlen(TEST_STR)) < 0)
		die("s write() failed: (%d) %s\n", errno, strerror(errno));

	if (++c == 2) {
		printf("bye\n");
		pause(); /* yawn */

		exit(0);
	}

	sock_sethandler_w(sock, NULL, NULL);
}

void
connection_around(sock_t *sock, void *data) {
	sock_t *talksock = sock_accept(sock);

	/* only one connection, thanks */
	sock_sethandler_r(sock, NULL, NULL);

	if (! talksock)
		return;

	sock_sethandler_r(talksock, NULL, NULL);
	sock_sethandler_w(talksock, write_now, NULL);

	if (! sockset_add(sockset, talksock))
		die("s sockset_add() failed: (%d) %s\n", errno, strerror(errno));
}


/* client */

void
read_now(sock_t *sock, void *data) {
	char buf[1024];

	sleep(1); /* to ensure that everything came here */

	if (read(sock->fd, buf, strlen(TEST_STR)) < 0)
		die("c read() failed: (%d) %s\n", errno, strerror(errno));
	buf[strlen(TEST_STR)] = 0;

	if (strcmp(buf, TEST_STR)) {
		die("%s doesn't match with %s.. wrong, man!\n", buf, TEST_STR);
	}

	if (++c == 2) {
		printf("bye\n");

		exit(0);
	}
}

void
connection_done(sock_t *sock, void *data) {
	sock_sethandler_r(sock, read_now, NULL);
	sock_sethandler_w(sock, NULL, NULL);
}


int
main(int argc, char *argv[]) {
	sock_t *sock1, *sock2;

	/* server */
	if (strstr(argv[0], "test2-srv")) {
		/* open two listening sockets */

		sock1 = sock_listen("", 65432, 1);
		if (! sock1)
			die("s sock_listen() failed: (%d) %s\n", errno, strerror(errno));

		sock_sethandler_r(sock1, connection_around, NULL);

		sock2 = sock_listen("", 65433, 1);
		if (! sock2)
			die("s sock_listen() failed: (%d) %s\n", errno, strerror(errno));

		sock_sethandler_r(sock2, connection_around, NULL);

		/* make sockset from them */

		sockset = sockset_get();
		if (! sockset)
			die("s sockset_get() failed: (%d) %s\n", errno, strerror(errno));

		if (! sockset_add(sockset, sock1))
			die("s sockset_add(sock1) failed: (%d) %s\n", errno, strerror(errno));

		if (! sockset_add(sockset, sock2))
			die("s sockset_add(sock2) failed: (%d) %s\n", errno, strerror(errno));

		/* and select */

		while (sockset_check(sockset)) usleep(50000); /* anti-overload */

		die("s sockset_check() failed: (%d) %s\n", errno, strerror(errno));

		/* client */
	} else {

		sleep(1);

		/* open two connecting sockets */

		sock1 = sock_connect("127.0.0.1", 65432, 1);
		if (! sock1)
			die("c sock_connect() failed: (%d) %s\n", errno, strerror(errno));

		sock_sethandler_r(sock1, connection_done, NULL);

		sock2 = sock_connect("127.0.0.1", 65433, 1);
		if (! sock2)
			die("c sock_connect() failed: (%d) %s\n", errno, strerror(errno));

		sock_sethandler_r(sock2, connection_done, NULL);

		/* make sockset from them */

		sockset = sockset_get();
		if (! sockset)
			die("c sockset_get() failed: (%d) %s\n", errno, strerror(errno));

		if (! sockset_add(sockset, sock1))
			die("c sockset_add(sock1) failed: (%d) %s\n", errno, strerror(errno));

		if (! sockset_add(sockset, sock2))
			die("c sockset_add(sock2) failed: (%d) %s\n", errno, strerror(errno));

		/* and select */

		while (sockset_check(sockset)) usleep(50000);

		die("c sockset_check() failed: (%d) %s\n", errno, strerror(errno));

#if 0
		if (read(s->fd, t, strlen(TEST_STR)) < 0)
			die("read() failed: (%d) %s\n", errno, strerror(errno));
		t[strlen(TEST_STR)] = 0;

		printf("c got %s, which ", t); fflush(stdout);
		if (! strcmp(t, TEST_STR)) {
			printf("matches! great!\n");
		} else {
			fprintf(stderr, "doesn't match with %s.. wrong, man!\n", TEST_STR);
			return 1;
		}
#endif
	}

	return 0;
}
