/*
 *  ircd-ratbox: A slightly useful ircd.
 *  s_serv.h: A header for the server functions.
 *
 *  Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
 *  Copyright (C) 1996-2002 Hybrid Development Team
 *  Copyright (C) 2002-2004 ircd-ratbox development team
 *
 *  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.
 *
 *  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
 */

#ifndef INCLUDED_serv_h
#define INCLUDED_serv_h

#include "defaults.h"
#include "capability.h"

/*
 * The number of seconds between calls to try_connections(). Fiddle with
 * this ONLY if you KNOW what you're doing!
 */
#define TRY_CONNECTIONS_TIME	60

/*
 * number of seconds to wait after server starts up, before
 * starting try_connections()
 * TOO SOON and you can nick collide like crazy.
 */
#define STARTUP_CONNECTIONS_TIME 60

struct Client;
struct server_conf;
struct Channel;

/* Capabilities */
extern struct CapabilityIndex *serv_capindex;
extern struct CapabilityIndex *cli_capindex;
extern uint64_t serv_clicapmask;

/* register client capabilities with this structure for 3.2 enhanced capability negotiation */
#define CLICAP_FLAGS_STICKY    0x001
#define CLICAP_FLAGS_PRIORITY  0x002
#define CLICAP_FLAGS_NOPROP    0x004
#define CLICAP_FLAGS_INVISIBLE 0x008

struct ClientCapability {
	bool (*visible)(struct Client *);		/* whether or not to display the capability.  set to NULL or true return value = displayed */
	const char *(*data)(struct Client *);		/* any custom data for the capability.  set to NULL or return NULL = no data */
	unsigned int flags;
};

/* builtin client capabilities */
extern uint64_t CLICAP_SERVONLY;           /* for s2s-only message tag propagation; no client ever has this cap */
extern uint64_t CLICAP_RECEIVE_LABEL;
extern uint64_t CLICAP_MULTI_PREFIX;
extern uint64_t CLICAP_ACCOUNT_NOTIFY;
extern uint64_t CLICAP_EXTENDED_JOIN;
extern uint64_t CLICAP_AWAY_NOTIFY;
extern uint64_t CLICAP_USERHOST_IN_NAMES;
extern uint64_t CLICAP_CAP_NOTIFY;
extern uint64_t CLICAP_CHGHOST;
extern uint64_t CLICAP_ECHO_MESSAGE;
extern uint64_t CLICAP_MESSAGE_TAGS;
extern uint64_t CLICAP_BATCH;
extern uint64_t CLICAP_NO_IMPLICIT_NAMES;
extern uint64_t CLICAP_LABELED_RESPONSE;

/*
 * XXX: this is kind of ugly, but this allows us to have backwards
 * API-compatibility.
 */
extern uint64_t CAP_CAP;			/* received a CAP to begin with */
extern uint64_t CAP_QS;			/* Can handle quit storm removal */
extern uint64_t CAP_EX;			/* Can do channel +e exemptions */
extern uint64_t CAP_CHW;			/* Can do channel wall @# */
extern uint64_t CAP_IE;			/* Can do invite exceptions */
extern uint64_t CAP_KLN;			/* Can do KLINE message */
extern uint64_t CAP_KNOCK;			/* supports KNOCK */
extern uint64_t CAP_TB;			/* supports TBURST */
extern uint64_t CAP_UNKLN;			/* supports remote unkline */
extern uint64_t CAP_CLUSTER;		/* supports cluster stuff */
extern uint64_t CAP_ENCAP;			/* supports ENCAP */
extern uint64_t CAP_TS6;			/* supports TS6 or above */
extern uint64_t CAP_SERVICE;		/* supports services */
extern uint64_t CAP_RSFNC;			/* rserv FNC */
extern uint64_t CAP_SAVE;			/* supports SAVE (nick collision FNC) */
extern uint64_t CAP_EUID;			/* supports EUID (ext UID + nonencap CHGHOST) */
extern uint64_t CAP_EOPMOD;			/* supports EOPMOD (ext +z + ext topic) */
extern uint64_t CAP_BAN;			/* supports propagated bans */
extern uint64_t CAP_MLOCK;			/* supports MLOCK messages */
extern uint64_t CAP_EBMASK;			/* supports sending BMASK set by/at metadata */
extern uint64_t CAP_STAG;			/* supports s2s tags and TAGMSG */

/* XXX: added for backwards compatibility. --nenolod */
#define CAP_MASK	(capability_index_mask(serv_capindex) & ~(CAP_TS6 | CAP_CAP))

/*
 * Capability macros.
 */
#define IsClientCapable(x, cap)         (((x)->localClient->client_caps & (cap)) == (cap))
#define NotClientCapable(x, cap)        (((x)->localClient->client_caps & (cap)) == 0)
#define SetClientCap(x, cap)            ((x)->localClient->client_caps |= (cap))
#define ClearClientCap(x, cap)          ((x)->localClient->client_caps &= ~(cap))
#define IsServerCapable(x, cap)         (((x)->localClient->server_caps & (cap)) == (cap))
#define NotServerCapable(x, cap)        (((x)->localClient->server_caps & (cap)) == 0)
#define SetServerCap(x, cap)            ((x)->localClient->server_caps |= (cap))
#define ClearServerCap(x, cap)          ((x)->localClient->server_caps &= ~(cap))

/*
 * Globals
 *
 *
 * list of recognized server capabilities.  "TS" is not on the list
 * because all servers that we talk to already do TS, and the kludged
 * extra argument to "PASS" takes care of checking that.  -orabidoo
 */
extern int MaxClientCount;	/* GLOBAL - highest number of clients */
extern int MaxConnectionCount;	/* GLOBAL - highest number of connections */

extern int refresh_user_links;

/*
 * return values for hunt_server()
 */
#define HUNTED_NOSUCH   (-1)	/* if the hunted server is not found */
#define HUNTED_ISME     0	/* if this server should execute the command */
#define HUNTED_PASS     1	/* if message passed onwards successfully */

extern void init_builtin_capabs(void);

extern int hunt_server(struct Client *client_pt,
		       struct Client *source_pt,
		       const char *command, int server, int parc, const char **parv);
extern void send_capabilities(struct Client *, uint64_t);
extern const char *show_capabilities(struct Client *client);
extern void try_connections(void *unused);

extern int check_server(const char *name, struct Client *server);
extern int server_estab(struct Client *client_p);

extern int serv_connect(struct server_conf *, struct Client *);

#endif /* INCLUDED_s_serv_h */
