/* Simple, blocking client API against the Osmocom CTRL interface */

/* (C) 2018 by Harald Welte <laforge@gnumonks.org>
 * All Rights Reserved.
 *
 * SPDX-License-Identifier: GPL-2.0+
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

#include <unistd.h>
#include <stdint.h>
#include <talloc.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <netinet/in.h>

#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include <osmocom/gsm/ipa.h>
#include <osmocom/gsm/protocol/ipaccess.h>

#include "client.h"
#include "simple_ctrl.h"

#define CTRL_ERR(sch, fmt, args...) \
	fprintf(stderr, "CTRL %s error: " fmt, make_authority(sch, &sch->cfg), ##args)

/***********************************************************************
 * blocking I/O with timeout helpers
 ***********************************************************************/

static struct timeval *timeval_from_msec(uint32_t tout_msec)
{
	static struct timeval tout;

	if (tout_msec == 0)
		return NULL;
	tout.tv_sec = tout_msec/1000;
	tout.tv_usec = (tout_msec%1000)*1000;

	return &tout;
}

static ssize_t read_timeout(int fd, void *buf, size_t count, uint32_t tout_msec)
{
	fd_set readset;
	int rc;

	FD_ZERO(&readset);
	FD_SET(fd, &readset);

	rc = select(fd+1, &readset, NULL, NULL, timeval_from_msec(tout_msec));
	if (rc < 0)
		return rc;

	if (FD_ISSET(fd, &readset))
		return read(fd, buf, count);

	return -ETIMEDOUT;
}

static ssize_t write_timeout(int fd, const void *buf, size_t count, uint32_t tout_msec)
{
	fd_set writeset;
	int rc;

	FD_ZERO(&writeset);
	FD_SET(fd, &writeset);

	rc = select(fd+1, NULL, &writeset, NULL, timeval_from_msec(tout_msec));
	if (rc < 0)
		return rc;

	if (FD_ISSET(fd, &writeset))
		return write(fd, buf, count);

	return -ETIMEDOUT;
}


/***********************************************************************
 * actual CTRL client API
 ***********************************************************************/

struct simple_ctrl_handle {
	int fd;
	uint32_t next_id;
	uint32_t tout_msec;
	struct host_cfg cfg;
};

struct simple_ctrl_handle *simple_ctrl_open(void *ctx, const char *host, uint16_t dport,
					    uint32_t tout_msec)
{
	struct simple_ctrl_handle *sch = talloc_zero(ctx, struct simple_ctrl_handle);
	fd_set writeset;
	int off = 0;
	int rc, fd;

	if (!sch)
		return NULL;

	sch->cfg.name = talloc_strdup(sch, "simple-ctrl");
	sch->cfg.remote_host = talloc_strdup(sch, host);
	sch->cfg.remote_port = dport;

	fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, host, dport,
			    OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK);
	if (fd < 0) {
		CTRL_ERR(sch, "connecting socket: %s\n", strerror(errno));
		return NULL;
	}

	/* wait until connect (or timeout) happens */
	FD_ZERO(&writeset);
	FD_SET(fd, &writeset);
	rc = select(fd+1, NULL, &writeset, NULL, timeval_from_msec(tout_msec));
	if (rc == 0) {
		CTRL_ERR(sch, "timeout during connect\n");
		goto out_close;
	}
	if (rc < 0) {
		CTRL_ERR(sch, "error connecting socket: %s\n", strerror(errno));
		goto out_close;
	}

	/* set FD blocking again */
	if (ioctl(fd, FIONBIO, (unsigned char *)&off) < 0) {
		CTRL_ERR(sch, "cannot set socket blocking: %s\n", strerror(errno));
		goto out_close;
	}

	sch->fd = fd;
	sch->tout_msec = tout_msec;
	return sch;

out_close:
	close(fd);
	return NULL;
}

void simple_ctrl_set_timeout(struct simple_ctrl_handle *sch, uint32_t tout_msec)
{
	sch->tout_msec = tout_msec;
}

void simple_ctrl_close(struct simple_ctrl_handle *sch)
{
	close(sch->fd);
	talloc_free(sch);
}

static struct msgb *simple_ipa_receive(struct simple_ctrl_handle *sch)
{
	struct ipaccess_head hh;
	struct msgb *resp;
	int rc, len;

	rc = read_timeout(sch->fd, (uint8_t *) &hh, sizeof(hh), sch->tout_msec);
	if (rc < 0) {
		CTRL_ERR(sch, "read(): %d\n", rc);
		return NULL;
	} else if (rc < sizeof(hh)) {
		CTRL_ERR(sch, "short read (header)\n");
		return NULL;
	}
	len = ntohs(hh.len);

	resp = msgb_alloc(len+sizeof(hh)+1, "CTRL Rx");
	if (!resp)
		return NULL;
	resp->l1h = msgb_put(resp, sizeof(hh));
	memcpy(resp->l1h, (uint8_t *) &hh, sizeof(hh));

	resp->l2h = resp->tail;
	rc = read(sch->fd, resp->l2h, len);
	if (rc < len) {
		CTRL_ERR(sch, "short read (payload)\n");
		msgb_free(resp);
		return NULL;
	}
	msgb_put(resp, rc);

	return resp;
}

struct msgb *simple_ctrl_receive(struct simple_ctrl_handle *sch)
{
	struct msgb *resp;
	struct ipaccess_head *ih;
	struct ipaccess_head_ext *ihe;
	unsigned char *tmp;

	/* loop until we've received a CTRL message */
	while (true) {
		resp = simple_ipa_receive(sch);
		if (!resp)
			return NULL;

		ih = (struct ipaccess_head *) resp->l1h;
		if (ih->proto == IPAC_PROTO_OSMO)
			resp->l2h = resp->l2h+1;
		ihe = (struct ipaccess_head_ext*) (resp->l1h + sizeof(*ih));
		if (ih->proto == IPAC_PROTO_OSMO && ihe->proto == IPAC_PROTO_EXT_CTRL) {
			/* Ensure data is NULL terminated */
			tmp = msgb_put(resp, 1);
			*tmp = '\0';
			return resp;
		} else {
			CTRL_ERR(sch, "unknown IPA message %s\n", msgb_hexdump(resp));
			msgb_free(resp);
		}
	}
}

static int simple_ctrl_send(struct simple_ctrl_handle *sch, struct msgb *msg)
{
	int rc;

	ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL);
	ipa_prepend_header(msg, IPAC_PROTO_OSMO);

	rc = write_timeout(sch->fd, msg->data, msg->len, sch->tout_msec);
	if (rc < 0) {
		CTRL_ERR(sch, "write(): %d\n", rc);
		return rc;
	} else if (rc < msg->len) {
		CTRL_ERR(sch, "short write\n");
		msgb_free(msg);
		return -1;
	} else {
		msgb_free(msg);
		return 0;
	}
}

static struct msgb *simple_ctrl_xceive(struct simple_ctrl_handle *sch, struct msgb *msg)
{
	int rc;

	rc = simple_ctrl_send(sch, msg);
	if (rc < 0)
		return NULL;

	/* FIXME: ignore any TRAP */
	return simple_ctrl_receive(sch);
}

char *simple_ctrl_get(struct simple_ctrl_handle *sch, const char *var)
{
	struct msgb *msg = msgb_alloc_headroom(512+8, 8, "CTRL GET");
	struct msgb *resp;
	unsigned int rx_id;
	char *rx_var, *rx_val;
	int rc;

	if (!msg)
		return NULL;

	rc = msgb_printf(msg, "GET %u %s", sch->next_id++, var);
	if (rc < 0) {
		msgb_free(msg);
		return NULL;
	}
	resp = simple_ctrl_xceive(sch, msg);
	if (!resp)
		return NULL;

	rc = sscanf(msgb_l2(resp), "GET_REPLY %u %ms %ms", &rx_id, &rx_var, &rx_val);
	if ((rc == 2) || (rc == 3)) {
		/* If body is empty return an empty string */
		if (rc == 2)
			rx_val = strdup("");

		if (rx_id == sch->next_id-1 && !strcmp(var, rx_var)) {
			free(rx_var);
			msgb_free(resp);
			return rx_val;
		}
		free(rx_var);
		free(rx_val);
	} else {
		CTRL_ERR(sch, "GET(%s) results in '%s'\n", var, (char *)msgb_l2(resp));
	}

	msgb_free(resp);
	return NULL;
}

int simple_ctrl_set(struct simple_ctrl_handle *sch, const char *var, const char *val)
{
	struct msgb *msg = msgb_alloc_headroom(512+8, 8, "CTRL SET");
	struct msgb *resp;
	unsigned int rx_id;
	char *rx_var, *rx_val;
	int rc;

	if (!msg)
		return -1;

	rc = msgb_printf(msg, "SET %u %s %s", sch->next_id++, var, val);
	if (rc < 0) {
		msgb_free(msg);
		return -1;
	}
	resp = simple_ctrl_xceive(sch, msg);
	if (!resp)
		return -1;

	if (sscanf(msgb_l2(resp), "SET_REPLY %u %ms %ms", &rx_id, &rx_var, &rx_val) == 3) {
		if (rx_id == sch->next_id-1 && !strcmp(var, rx_var) && !strcmp(val, rx_val)) {
			free(rx_val);
			free(rx_var);
			msgb_free(resp);
			return 0;
		} else {
			free(rx_val);
			free(rx_var);
		}
	} else {
		CTRL_ERR(sch, "SET(%s=%s) results in '%s'\n", var, val, (char *) msgb_l2(resp));
	}

	msgb_free(resp);
	return -1;
}
