/*
 * lws-minimal-http-client-post
 *
 * Written in 2010-2019 by Andy Green <andy@warmcat.com>
 *
 * This file is made available under the Creative Commons CC0 1.0
 * Universal Public Domain Dedication.
 *
 * This demonstrates the a minimal http client using lws and POST.
 *
 * It POSTs both form data and a file to the form at
 * https://libwebsockets.org/testserver/formtest and dumps
 * the html page received generated by the POST handler.
 */

#include <libwebsockets.h>
#include <string.h>
#include <signal.h>

static int interrupted, bad = 0, status, completed;
static struct lws *client_wsi;

struct pss {
	char body_part;
};
int totallen = 2;
char sentdata[10000];
//int sentlen = 0;
char sendchar[20];
void readnffile() {
	FILE *f = fopen("/home/cavisson/Desktop/nfrequest.txt", "rb");
	fseek(f, 0, SEEK_END);
	int fsize = ftell(f);
	fseek(f, 0, SEEK_SET);  /* same as rewind(f); */

	fread(sentdata, fsize, 1, f);
	fclose(f);
		sentdata[fsize] = 0;
int sentlen = strlen(sentdata);
memset(sendchar,0,20);
sprintf(sendchar,"%d",sentlen);
if(sentlen > 99)
totallen = 3;
if(sentlen > 999)
totallen = 4;

}
int ii = 0;

const char *contentType = "application/json";
static int
callback_http(struct lws *wsi, enum lws_callback_reasons reason,
	      void *user, void *in, size_t len)
{
	struct pss *pss = (struct pss *)user;
	int nw;
	uint8_t buf[LWS_PRE + 10000], *start = &buf[LWS_PRE], *p = start,
		*end = &buf[sizeof(buf) - LWS_PRE - 1];
	int n;

	switch (reason) {

	/* because we are protocols[0] ... */
	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
	fprintf(stderr, "execute LWS_CALLBACK_CLIENT_CONNECTION_ERROR\n");
		bad = 1;
		lws_cancel_service(lws_get_context(wsi));
		break;

	case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
		fprintf(stderr, "execute LWS_CALLBACK_CLOSED_CLIENT_HTTP\n");
		client_wsi = NULL;
		bad |= status != 200;
		lws_cancel_service(lws_get_context(wsi));
		break;

	case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
	
		status = (int)lws_http_client_http_response(wsi);
		fprintf(stderr, "execute LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP %d\n",status);
		break;

	case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
		fprintf(stderr, "execute LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ\n");
		fprintf(stderr, "execute code %d len %d and %s\n", __LINE__,(int)len,(char*)in);
		return 0; /* don't passthru */

	case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
		
		n = sizeof(buf) - LWS_PRE;
		//n = strlen(sentdata);
		fprintf(stderr, "execute LWS_CALLBACK_RECEIVE_CLIENT_HTTP %d\n",n);
		if (lws_http_client_read(wsi, (char**)&p, &n) < 0)
			return -1;
		fprintf(stderr, "execute code %d  %d and %s\n", __LINE__,n,p);
		return 0; /* don't passthru */

	case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
		fprintf(stderr, "execute LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n");
		bad |= status != 200;
		client_wsi = NULL;
		lws_cancel_service(lws_get_context(wsi));
		break;

	case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
	
		fprintf(stderr, "execute LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER\n");
		unsigned char **p1 = (unsigned char **)in, *end1 = (*p1) + len;

			if (lws_add_http_header_by_token(wsi,
					WSI_TOKEN_HTTP_CONTENT_LENGTH,
					(unsigned char *)sendchar, totallen, p1, end1))
				return -1;
			if (lws_add_http_header_by_token(wsi,
					WSI_TOKEN_HTTP_CONTENT_TYPE,
					(unsigned char *)"application/json",
					16, p1, end1))
				return -1;
			lws_client_http_body_pending(wsi, 1);
			lws_callback_on_writable(wsi);
				break;

	case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
		fprintf(stderr, "execute LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n");
		if (lws_http_is_redirected_to_get(wsi))
			break;

		lws_write(wsi, sentdata, strlen(sentdata),LWS_WRITE_HTTP);
		lws_client_http_body_pending(wsi, 0);

		return 0;

	default:
		break;
	}

	return lws_callback_http_dummy(wsi, reason, user, in, len);
}

static const struct lws_protocols protocols[] = {
	{
		"http",
		callback_http,
		sizeof(struct pss),
		0, 0, NULL, 0
	},
	LWS_PROTOCOL_LIST_TERM
};

static void
sigint_handler(int sig)
{
	interrupted = 1;
}

int main(int argc, const char **argv)
{
	struct lws_context_creation_info info;
	struct lws_client_connect_info i;
	struct lws_context *context;
	const char *p;
	int n = 0;

	signal(SIGINT, sigint_handler);
	memset(sentdata,0,10000);

	readnffile();
	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
	lws_cmdline_option_handle_builtin(argc, argv, &info);
	lwsl_user("LWS minimal http client - POST [-d<verbosity>] [-l] [--h1]\n");

	info.options = 0;//LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
	info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
	info.protocols = protocols;
	info.fd_limit_per_thread = (unsigned int)(1 + 1 + 1);

#if defined(LWS_WITH_MBEDTLS) || defined(USE_WOLFSSL)
	fprintf(stderr, "execute code %d\n", __LINE__);
	if (!lws_cmdline_option(argc, argv, "-l"))
		info.client_ssl_ca_filepath = "./libwebsockets.org.cer";
#endif

	context = lws_create_context(&info);
	if (!context) {
		lwsl_err("lws init failed\n");
		return 1;
	}

	memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
	i.context = context;
	i.ssl_connection = 0;//LCCSCF_HTTP_MULTIPART_MIME;//LCCSCF_USE_SSL

	if (lws_cmdline_option(argc, argv, "-l")) {
		fprintf(stderr, "execute code %d\n", __LINE__);
		i.address = "172.24.0.193";
		i.path = "/nd_nfparse";
		i.port=1234;
	} else {
		//i.port = 443;
		fprintf(stderr, "execute code %d\n", __LINE__);
		//i.address = "libwebsockets.org";
		//i.path = "/testserver/formtest";

		i.address = "10.20.0.71";
		i.path = "/nd_nfparse";
		i.port=9999;
	}

	if (lws_cmdline_option(argc, argv, "--form1"))
		i.path = "/form1";

	if ((p = lws_cmdline_option(argc, argv, "--port")))
		i.port = atoi(p);
	
	i.host = i.address;
	i.origin = i.address;
	i.method = "POST";

	/* force h1 even if h2 available */
	if (lws_cmdline_option(argc, argv, "--h1")) {
		fprintf(stderr, "execute code %d\n", __LINE__);
		i.alpn = "http/1.1";
	}
	//i.alpn = "http/1.1";
	i.protocol = protocols[0].name;

	i.pwsi = &client_wsi;
	lwsl_notice("%s: connecting to %s:%d\n", __func__,
		    i.address, i.port);
	if (!lws_client_connect_via_info(&i))
		completed++;

	while (n >= 0 && !interrupted)
		n = lws_service(context, 0);
	fprintf(stderr, "execute code %d\n", __LINE__);
	lws_context_destroy(context);
	lwsl_user("Completed: %s\n", bad ? "failed" : "OK");

	return bad;
}

