/*
 * http_server - HTTP server
 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "includes.h"
#include <fcntl.h>

#include "common.h"
#include "eloop.h"
#include "httpread.h"
#include "http_server.h"

#define HTTP_SERVER_TIMEOUT 30
#define HTTP_SERVER_MAX_REQ_LEN 8000
#define HTTP_SERVER_MAX_CONNECTIONS 10

struct http_request {
	struct http_request *next;
	struct http_server *srv;
	int fd;
	struct sockaddr_in cli;
	struct httpread *hread;
};

struct http_server {
	void (*cb)(void *ctx, struct http_request *req);
	void *cb_ctx;

	int fd;
	int port;

	struct http_request *requests;
	unsigned int request_count;
};


static void http_request_cb(struct httpread *handle, void *cookie,
			    enum httpread_event en)
{
	struct http_request *req = cookie;
	struct http_server *srv = req->srv;

	if (en == HTTPREAD_EVENT_FILE_READY) {
		wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d received",
			   inet_ntoa(req->cli.sin_addr),
			   ntohs(req->cli.sin_port));
		srv->cb(srv->cb_ctx, req);
		return;
	}
	wpa_printf(MSG_DEBUG, "HTTP: Request from %s:%d could not be received "
		   "completely", inet_ntoa(req->cli.sin_addr),
		   ntohs(req->cli.sin_port));
	http_request_deinit(req);
}


static struct http_request * http_request_init(struct http_server *srv, int fd,
					       struct sockaddr_in *cli)
{
	struct http_request *req;

	if (srv->request_count >= HTTP_SERVER_MAX_CONNECTIONS) {
		wpa_printf(MSG_DEBUG, "HTTP: Too many concurrent requests");
		return NULL;
	}

	req = os_zalloc(sizeof(*req));
	if (req == NULL)
		return NULL;

	req->srv = srv;
	req->fd = fd;
	req->cli = *cli;

	req->hread = httpread_create(req->fd, http_request_cb, req,
				     HTTP_SERVER_MAX_REQ_LEN,
				     HTTP_SERVER_TIMEOUT);
	if (req->hread == NULL) {
		http_request_deinit(req);
		return NULL;
	}

	return req;
}


void http_request_deinit(struct http_request *req)
{
	struct http_request *r, *p;
	struct http_server *srv;

	if (req == NULL)
		return;

	srv = req->srv;
	p = NULL;
	r = srv->requests;
	while (r) {
		if (r == req) {
			if (p)
				p->next = r->next;
			else
				srv->requests = r->next;
			srv->request_count--;
			break;
		}
		p = r;
		r = r->next;
	}

	httpread_destroy(req->hread);
	close(req->fd);
	os_free(req);
}


static void http_request_free_all(struct http_request *req)
{
	struct http_request *prev;
	while (req) {
		prev = req;
		req = req->next;
		http_request_deinit(prev);
	}
}


void http_request_send(struct http_request *req, struct wpabuf *resp)
{
	int res;

	wpa_printf(MSG_DEBUG, "HTTP: Send %lu byte response to %s:%d",
		   (unsigned long) wpabuf_len(resp),
		   inet_ntoa(req->cli.sin_addr),
		   ntohs(req->cli.sin_port));

	res = send(req->fd, wpabuf_head(resp), wpabuf_len(resp), 0);
	if (res < 0) {
		wpa_printf(MSG_DEBUG, "HTTP: Send failed: %s",
			   strerror(errno));
	} else if ((size_t) res < wpabuf_len(resp)) {
		wpa_printf(MSG_DEBUG, "HTTP: Sent only %d of %lu bytes",
			   res, (unsigned long) wpabuf_len(resp));
		/* TODO: add eloop handler for sending rest of the data */
	}

	wpabuf_free(resp);
}


void http_request_send_and_deinit(struct http_request *req,
				  struct wpabuf *resp)
{
	http_request_send(req, resp);
	http_request_deinit(req);
}


enum httpread_hdr_type http_request_get_type(struct http_request *req)
{
	return httpread_hdr_type_get(req->hread);
}


char * http_request_get_uri(struct http_request *req)
{
	return httpread_uri_get(req->hread);
}


char * http_request_get_hdr(struct http_request *req)
{
	return httpread_hdr_get(req->hread);
}


char * http_request_get_data(struct http_request *req)
{
	return httpread_data_get(req->hread);
}


char * http_request_get_hdr_line(struct http_request *req, const char *tag)
{
	return httpread_hdr_line_get(req->hread, tag);
}


struct sockaddr_in * http_request_get_cli_addr(struct http_request *req)
{
	return &req->cli;
}


static void http_server_cb(int sd, void *eloop_ctx, void *sock_ctx)
{
	struct sockaddr_in addr;
	socklen_t addr_len = sizeof(addr);
	struct http_server *srv = eloop_ctx;
	int conn;
	struct http_request *req;

	conn = accept(srv->fd, (struct sockaddr *) &addr, &addr_len);
	if (conn < 0) {
		wpa_printf(MSG_DEBUG, "HTTP: Failed to accept new connection: "
			   "%s", strerror(errno));
		return;
	}
	wpa_printf(MSG_DEBUG, "HTTP: Connection from %s:%d",
		   inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

	req = http_request_init(srv, conn, &addr);
	if (req == NULL) {
		close(conn);
		return;
	}

	req->next = srv->requests;
	srv->requests = req;
	srv->request_count++;
}


struct http_server * http_server_init(struct in_addr *addr, int port,
				      void (*cb)(void *ctx,
						 struct http_request *req),
				      void *cb_ctx)
{
	struct sockaddr_in sin;
	struct http_server *srv;

	srv = os_zalloc(sizeof(*srv));
	if (srv == NULL)
		return NULL;
	srv->cb = cb;
	srv->cb_ctx = cb_ctx;

	srv->fd = socket(AF_INET, SOCK_STREAM, 0);
	if (srv->fd < 0)
		goto fail;
	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
		goto fail;
	if (port < 0)
		srv->port = 49152;
	else
		srv->port = port;

	os_memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = addr->s_addr;

	for (;;) {
		sin.sin_port = htons(srv->port);
		if (bind(srv->fd, (struct sockaddr *) &sin, sizeof(sin)) == 0)
			break;
		if (errno == EADDRINUSE) {
			/* search for unused port */
			if (++srv->port == 65535 || port >= 0)
				goto fail;
			continue;
		}
		wpa_printf(MSG_DEBUG, "HTTP: Failed to bind server port %d: "
			   "%s", srv->port, strerror(errno));
		goto fail;
	}
	if (listen(srv->fd, 10 /* max backlog */) < 0)
		goto fail;
	if (fcntl(srv->fd, F_SETFL, O_NONBLOCK) < 0)
		goto fail;
	if (eloop_register_sock(srv->fd, EVENT_TYPE_READ, http_server_cb,
				srv, NULL))
		goto fail;

	wpa_printf(MSG_DEBUG, "HTTP: Started server on %s:%d",
		   inet_ntoa(*addr), srv->port);

	return srv;

fail:
	http_server_deinit(srv);
	return NULL;
}


void http_server_deinit(struct http_server *srv)
{
	if (srv == NULL)
		return;
	if (srv->fd >= 0) {
		eloop_unregister_sock(srv->fd, EVENT_TYPE_READ);
		close(srv->fd);
	}
	http_request_free_all(srv->requests);

	os_free(srv);
}


int http_server_get_port(struct http_server *srv)
{
	return srv->port;
}
