/*-
 * Copyright 2016 Vsevolod Stakhov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef RSPAMD_RSPAMD_CONTROL_H
#define RSPAMD_RSPAMD_CONTROL_H

#include "config.h"
#include "mem_pool.h"
#include <event.h>

struct rspamd_main;
struct rspamd_worker;

enum rspamd_control_type {
	RSPAMD_CONTROL_STAT = 0,
	RSPAMD_CONTROL_RELOAD,
	RSPAMD_CONTROL_RERESOLVE,
	RSPAMD_CONTROL_RECOMPILE,
	RSPAMD_CONTROL_HYPERSCAN_LOADED,
	RSPAMD_CONTROL_LOG_PIPE,
	RSPAMD_CONTROL_FUZZY_STAT,
	RSPAMD_CONTROL_FUZZY_SYNC,
	RSPAMD_CONTROL_MAX
};

enum rspamd_srv_type {
	RSPAMD_SRV_SOCKETPAIR = 0,
	RSPAMD_SRV_HYPERSCAN_LOADED,
	RSPAMD_SRV_LOG_PIPE,
};

enum rspamd_log_pipe_type {
	RSPAMD_LOG_PIPE_SYMBOLS = 0,
};

struct rspamd_control_command {
	enum rspamd_control_type type;
	union {
		struct {
			guint unused;
		} stat;
		struct {
			guint unused;
		} reload;
		struct {
			guint unused;
		} reresolve;
		struct {
			guint unused;
		} recompile;
		struct {
			gpointer cache_dir;
			gboolean forced;
		} hs_loaded;
		struct {
			enum rspamd_log_pipe_type type;
		} log_pipe;
		struct {
			guint unused;
		} fuzzy_stat;
		struct {
			guint unused;
		} fuzzy_sync;
	} cmd;
};

struct rspamd_control_reply {
	enum rspamd_control_type type;
	union {
		struct {
			guint conns;
			gdouble uptime;
			gdouble utime;
			gdouble systime;
			gulong maxrss;
		} stat;
		struct {
			guint status;
		} reload;
		struct {
			guint status;
		} reresolve;
		struct {
			guint status;
		} recompile;
		struct {
			guint status;
		} hs_loaded;
		struct {
			guint status;
		} log_pipe;
		struct {
			guint status;
			gchar storage_id[MEMPOOL_UID_LEN];
		} fuzzy_stat;
		struct {
			guint status;
		} fuzzy_sync;
	} reply;
};

#define PAIR_ID_LEN 16
struct rspamd_srv_command {
	enum rspamd_srv_type type;
	guint64 id;
	union {
		struct {
			gint af;
			gchar pair_id[PAIR_ID_LEN];
			guint pair_num;
		} spair;
		struct {
			gpointer cache_dir;
			gboolean forced;
		} hs_loaded;
		struct {
			enum rspamd_log_pipe_type type;
		} log_pipe;
	} cmd;
};

struct rspamd_srv_reply {
	enum rspamd_srv_type type;
	guint64 id;
	union {
		struct {
			gint code;
		} spair;
		struct {
			gint forced;
		} hs_loaded;
		struct {
			enum rspamd_log_pipe_type type;
		} log_pipe;
	} reply;
};

typedef gboolean (*rspamd_worker_control_handler) (struct rspamd_main *rspamd_main,
		struct rspamd_worker *worker,
		gint fd,
		gint attached_fd,
		struct rspamd_control_command *cmd,
		gpointer ud);

typedef void (*rspamd_srv_reply_handler) (struct rspamd_worker *worker,
		struct rspamd_srv_reply *rep, gint rep_fd,
		gpointer ud);

/**
 * Process client socket connection
 */
void rspamd_control_process_client_socket (struct rspamd_main *rspamd_main,
		gint fd);

/**
 * Register default handlers for a worker
 */
void rspamd_control_worker_add_default_handler (struct rspamd_worker *worker,
		struct event_base *ev_base);

/**
 * Register custom handler for a specific control command for this worker
 */
void rspamd_control_worker_add_cmd_handler (struct rspamd_worker *worker,
		enum rspamd_control_type type,
		rspamd_worker_control_handler handler,
		gpointer ud);

/**
 * Start watching on srv pipe
 */
void rspamd_srv_start_watching (struct rspamd_worker *worker,
		struct event_base *ev_base);


/**
 * Send command to srv pipe and read reply calling the specified callback at the
 * end
 */
void rspamd_srv_send_command (struct rspamd_worker *worker,
		struct event_base *ev_base,
		struct rspamd_srv_command *cmd,
		gint attached_fd,
		rspamd_srv_reply_handler handler,
		gpointer ud);
#endif
