#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <sys/select.h>
#include <curl/curl.h>

static int unix_wait(curl_socket_t sockfd, unsigned sending, unsigned timeout)
{
	fd_set fds, *rfds = sending ? NULL : &fds, *wfds = sending ? &fds : NULL;
	struct timeval tv = { timeout, 0 };
	int rv;

	FD_ZERO(&fds);
	FD_SET(sockfd, &fds);
	rv = select(sockfd + 1, rfds, wfds, NULL, &tv);
	return rv > 0 ? 0 /*ready*/ : rv < 0 ? rv /*err*/ : 1 /*timeout*/;
}

static const char command[] = "A013 LOGOUT\r\n";
static char buf[4096];

int main(void)
{
	CURL *curl;
	unsigned loop;

	assert(curl_global_init(CURL_GLOBAL_ALL) == CURLE_OK);
	fprintf(stderr, "using curl %s\n", curl_version_info(0)->version);
	assert((curl = curl_easy_init()));
	assert(curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L) == CURLE_OK);
	assert(curl_easy_setopt(curl, CURLOPT_MAXCONNECTS, 1L) == CURLE_OK);
	assert(curl_easy_setopt(curl, CURLOPT_USERNAME, "test") == CURLE_OK);
	assert(curl_easy_setopt(curl, CURLOPT_PASSWORD, "test") == CURLE_OK);
	assert(curl_easy_setopt(curl, CURLOPT_URL, "imap://localhost:43143") == CURLE_OK);
	assert(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L) == CURLE_OK);
	for (loop = 1; loop <= 10; loop++) {
		curl_socket_t sockfd;
		size_t done, n;

		printf("loop[%u] perform\n", loop);
		assert(curl_easy_perform(curl) == CURLE_OK);
		assert(curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd) == CURLE_OK);
		for (done = 0; done < sizeof(command) - 1; done += n) {
			CURLcode res = curl_easy_send(curl, command + done, sizeof(command) - 1 - done, &n);

			if (res == CURLE_OK) {
				fprintf(stderr, "loop[%u] sent %zu\n", loop, n);
				if (!n)
					break;
			} else if (res == CURLE_AGAIN) {
				fprintf(stderr, "loop[%u] wait send\n", loop);
				if (unix_wait(sockfd, 1, 10))
					break;
			} else {
				abort();
			}
		}
		if (done == sizeof(command) - 1) {
			for (done = 0; done < sizeof(buf); done += n) {
				CURLcode res = curl_easy_recv(curl, buf + done, sizeof(buf) - done, &n);

				if (res == CURLE_OK) {
					fprintf(stderr, "loop[%u] recv %zu\n", loop, n);
					if (!n)
						break;
				} else if (res == CURLE_AGAIN) {
					fprintf(stderr, "loop[%u] wait recv\n", loop);
					if (unix_wait(sockfd, 0, 3))
						break;
				} else {
					abort();
				}
			}
			if (done)
				printf("loop[%u] response:%.*s--------\n", loop, (int) done, buf);
		}
	}

	return 0;
}

