/**
 * Copyright 2016 (C) Orange
 * <camille.oudot@orange.com>
 *
 * This file is part of Kamailio, a free SIP server.
 *
 * This file 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 file 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdio.h>
#include <systemd/sd-journal.h>

#include "../../xavp.h"
#include "../../dprint.h"
#include "../../mem/pkg.h"

#include "journal_send.h"

int k_sd_journal_send_xavp(str *rname)
{
	struct _sr_xavp *rxavp, *nxavp;
	int cnt, buflen, i, ret;
	struct iovec *logv;

	rxavp = xavp_get(rname, NULL);

	if (!rxavp || rxavp->val.type != SR_XTYPE_XAVP) {
		LM_ERR("not a valid xavp: %.*s?\n", rname->len, rname->s);
	}

	/* first, count xavp nodes */
	for (nxavp = rxavp->val.v.xavp, cnt = 0;
			nxavp;
			nxavp = nxavp->next, cnt++);

	if (cnt == 0) {
		/* nothing to log? */
		LM_NOTICE("empty xavp: %.*s?, no log event was sent to journald\n",
				rname->len,
				rname->s);
		return 1;
	}

	logv = pkg_malloc(cnt * sizeof (struct iovec));

	if (!logv) {
		LM_ERR("failed to allocate pkg memory\n");
		return -1;
	}

	ret = -1;

	for (nxavp = rxavp->val.v.xavp, cnt = 0;
			nxavp;
			nxavp = nxavp->next, cnt++)
	{
		if (nxavp->val.type == SR_XTYPE_INT) {
			buflen = snprintf(NULL, 0,
					"%.*s=%d",
					nxavp->name.len, nxavp->name.s,
					nxavp->val.v.i);
			logv[cnt].iov_base = pkg_malloc(buflen + 1/*snprintf's trailing \0*/);
			if (!logv[cnt].iov_base ) {
				LM_ERR("failed to allocate pkg memory\n");
				goto free;
			}
			logv[cnt].iov_len = buflen;

			snprintf(logv[cnt].iov_base, buflen + 1,
					"%.*s=%d",
					nxavp->name.len, nxavp->name.s,
					nxavp->val.v.i);
		} else if (nxavp->val.type == SR_XTYPE_STR) {
			buflen = nxavp->name.len + 1 + nxavp->val.v.s.len;
			logv[cnt].iov_base = pkg_malloc(buflen);
			if (!logv[cnt].iov_base) {
				LM_ERR("failed to allocate pkg memory\n");
				goto free;
			}
			logv[cnt].iov_len = buflen;

			memcpy(logv[cnt].iov_base, nxavp->name.s, nxavp->name.len);
			((char*)logv[cnt].iov_base)[nxavp->name.len] = '=';
			memcpy(((char*)(logv[cnt].iov_base)) + nxavp->name.len + 1,
					nxavp->val.v.s.s,
					nxavp->val.v.s.len);
		} else {
			LM_NOTICE("unsupported type %d for field %.*s, skipped...\n",
					nxavp->val.type,
					nxavp->name.len, nxavp->name.s);
			logv[cnt].iov_len = 0;
			logv[cnt].iov_base = NULL;
		}
		LM_DBG("added io slice %d: %.*s\n", cnt, (int)logv[cnt].iov_len, (char*)logv[cnt].iov_base);
	}

	if (sd_journal_sendv(logv, cnt) != 0) {
		LM_ERR("sd_journal_sendv() failed\n");
	} else {
		ret = 1;
	}

free:
	for (i = 0 ; i < cnt ; i++) {
		if (logv[i].iov_base) pkg_free(logv[i].iov_base);
	}
	pkg_free(logv);
	return ret;
}