/*
 * Copyright (C) 2016 - OpenSIPS Solutions
 *
 * This file is part of opensips, a free SIP server.
 *
 * opensips 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
 *
 * opensips 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * History:
 * -------
 *  2016-09-19  first version (Ionut Ionita)
 */
#ifndef _mi_trace_h
#define _mi_trace_h

#include "../trace_api.h"

extern trace_proto_t* mi_trace_api;
extern int correlation_id, correlation_vendor;
extern str correlation_value;

#define MAX_TRACE_FIELD (1 << 7)

struct mi_trace_req {
	str cmd;
	str backend;
	char params[MAX_TRACE_FIELD];
};

extern str mi_trpl;

enum mi_trace_type { MI_TRACE_REQ, MI_TRACE_RPL};

struct mi_trace_param {
	enum mi_trace_type type;
	union {
		struct mi_trace_req* req;
		str *rpl;
	} d;
};

extern struct mi_trace_param mi_tparam;

void try_load_trace_api(void);

int trace_mi_message(const union sockaddr_union* src, const union sockaddr_union* dst,
	struct mi_trace_param* pld_param, str* correlation_value, trace_dest trace_dst);

struct mi_trace_req* build_mi_trace_request(str *cmd, mi_item_t *params,
										str* backend);

str *build_mi_trace_reply(str *rpl_msg);
char* generate_correlation_id(int* len);;
int load_correlation_id(void);

static inline void mi_trace_reply( const union sockaddr_union* src, const union sockaddr_union* dst,
		str* message, trace_dest t_dst)
{
	/* trace disabled */
	if ( !t_dst )
		return;

	if (!message) {
		LM_ERR("Empty MI reply!\n");
		return;
	}

	mi_tparam.d.rpl = build_mi_trace_reply(message);
	mi_tparam.type = MI_TRACE_RPL;

	if ( !correlation_value.s ) {
		LM_ERR("can't find correlation id generated by the request!\n");
		return;
	}

	if (trace_mi_message( src, dst, &mi_tparam, &correlation_value, t_dst) < 0) {
		LM_ERR("failed to trace mi command reply!\n");
	}
}


static inline void mi_trace_request( const union sockaddr_union* src, const union sockaddr_union* dst,
		char* command, int len, mi_item_t *params, str* backend, trace_dest t_dst )
{
	str comm_s = { command, len };

	if ( !t_dst || !backend )
		return;

	mi_tparam.d.req = build_mi_trace_request( &comm_s, params, backend);
	if (!mi_tparam.d.req) {
		LM_ERR("Failed to prepare payload for tracing request\n");
		return;
	}
	mi_tparam.type = MI_TRACE_REQ;

	correlation_value.s = generate_correlation_id(&correlation_value.len);

	if ( !correlation_value.s ) {
		LM_ERR("failed to generate correlation id!\n");
		return;
	}

	if (trace_mi_message( src, dst, &mi_tparam, &correlation_value, t_dst) < 0) {
		LM_ERR("failed to trace mi command request!\n");
	}
}

int register_mi_trace_mod(void);
int init_mod_trace_cmds(int id, int white);

int block_mi_cmd_trace(int id, char* name, int len);
int allow_mi_cmd_trace(int id, char* name, int len);
unsigned char is_mi_cmd_traced(int id, struct mi_cmd* cmd);
int parse_mi_cmd_bwlist(int id, char* bw_string, int len);



#endif
