/* inerface.h */

#include "copyright.h"

#ifndef __INTERFACE__H
#define __INTERFACE__H

#include "db.h"
#include "externs.h"
#include "htab.h"

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

/* these symbols must be defined by the interface */

extern int shutdown_flag; /* if non-zero, interface should shut down */

/* Disconnection reason codes */

#define	R_QUIT		1	/* User quit */
#define	R_TIMEOUT	2	/* Inactivity timeout */
#define	R_BOOT		3	/* Victim of @boot, @toad, or @destroy */
#define	R_SOCKDIED	4	/* Other end of socked closed it */
#define	R_GOING_DOWN	5	/* Game is going down */
#define	R_BADLOGIN	6	/* Too many failed login attempts */
#define	R_GAMEDOWN	7	/* Not admitting users now */
#define	R_LOGOUT	8	/* Logged out w/o disconnecting */
#define R_GAMEFULL	9	/* Too many players logged in */

/* Logged out command table definitions */

#define	CMD_QUIT	1
#define	CMD_WHO		2
#define	CMD_DOING	3
#define	CMD_RWHO	4
#define	CMD_PREFIX	5
#define	CMD_SUFFIX	6
#define	CMD_LOGOUT	7
#define	CMD_SESSION	8

#define	CMD_MASK	0xff
#define	CMD_NOxFIX	0x100

extern NAMETAB logout_cmdtable[];

typedef struct cmd_block_hdr CBLKHDR;
typedef struct cmd_block CBLOCK;

struct cmd_block {
	struct cmd_block_hdr {
		struct cmd_block *nxt;
	}	hdr;
	char	cmd[LBUF_SIZE - sizeof(CBLKHDR)];
};

typedef struct text_block_hdr TBLKHDR;
typedef struct text_block TBLOCK;

struct text_block {
	struct text_block_hdr {
		struct text_block *nxt;
		char	*start;
		char	*end;
		int	nchars;
	}	hdr;
	char	data[LBUF_SIZE - sizeof(TBLKHDR)];
};

typedef struct descriptor_data DESC;
struct descriptor_data {
  int descriptor;
  int flags;
  int retries_left;
  int command_count;
  int timeout;
  int host_info;
  char addr[51];
  char doing[41];
  dbref player;
  char *output_prefix;
  char *output_suffix;
  int output_size;
  int output_tot;
  int output_lost;
  TBLOCK *output_head;
  TBLOCK *output_tail;
  int input_size;
  int input_tot;
  int input_lost;
  CBLOCK *input_head;
  CBLOCK *input_tail;
  char *raw_input;
  char *raw_input_at;
  time_t connected_at;
  time_t last_time;
  int quota;
  struct sockaddr_in address;	/* added 3/6/90 SCG */
  struct descriptor_data *hashnext;
  struct descriptor_data *next;
  struct descriptor_data **prev;
};

/* flags in the flag field */
#define	DS_CONNECTED	0x0001		/* player is connected */
#define	DS_AUTODARK	0x0002		/* Wizard was auto set dark. */

extern DESC *descriptor_list;

/* from the net interface */

extern void emergency_shutdown();
extern void shutdownsock (DESC *d, int reason);
extern void shovechars(int port);
extern void set_signals();
extern void dump_text (int descriptor, FBLOCK *fb);

/* from netcommon.c */

extern struct timeval timeval_sub(struct timeval now, struct timeval then);
extern int msec_diff(struct timeval now, struct timeval then);
extern struct timeval msec_add(struct timeval t, int x);
extern struct timeval update_quotas(struct timeval last,
	struct timeval current);
extern void raw_notify(dbref player, const char *msg);
extern void raw_broadcast ();
extern void clearstrings(DESC *d);
extern void queue_write(DESC *d, const char *b, int n);
extern void queue_string(DESC *d, const char *s);
extern void freeqs(DESC *d);
extern void welcome_user(DESC *d);
extern int fcache_read (FBLOCK **cp, char *filename);
extern void fcache_dump (DESC *d, FBLOCK *fp);
extern void fcache_send (dbref player, FBLOCK *fp);
extern void fcache_load (dbref player);
extern void fcache_init (void);
extern void save_command(DESC *d, const char *command);
extern void announce_disconnect(dbref player, DESC *d, const char *reason);
extern int boot_off (dbref player, char *message);
extern int boot_by_port (int port, int no_god, char *message);
extern void check_idle();
extern void dump_users(DESC *e, char *match, int key);
extern int do_command(DESC *d, char *command);
extern void process_commands();
extern int site_check (struct in_addr host, SITE *site_list);
extern void make_ulist (dbref player, char *buff);
extern dbref find_connected_name (dbref player, char *name);

/* From predicates.c */

#define alloc_desc(s) (DESC *)pool_alloc(&mudstate.desc_pool,s)
#define free_desc(b) pool_free(&mudstate.desc_pool,((char **)&(b)))

#define DESC_ITER_PLAYER(p,d) \
	for (d=(DESC *)nhashfind((int)p,&mudstate.desc_htab);d;d=d->hashnext)
#define DESC_ITER_CONN(d) \
	for (d=descriptor_list;(d);d=(d)->next) \
		if ((d)->flags & DS_CONNECTED)
#define DESC_ITER_ALL(d) \
	for (d=descriptor_list;(d);d=(d)->next)

#define DESC_SAFEITER_PLAYER(p,d,n) \
	for (d=(DESC *)nhashfind((int)p,&mudstate.desc_htab), \
        	n=((d!=NULL) ? d->hashnext : NULL); \
	     d; \
	     d=n,n=((n!=NULL) ? n->hashnext : NULL))
#define DESC_SAFEITER_CONN(d,n) \
	for (d=descriptor_list,n=((d!=NULL) ? d->next : NULL); \
	     d; \
	     d=n,n=((n!=NULL) ? n->next : NULL)) \
		if ((d)->flags & DS_CONNECTED)
#define DESC_SAFEITER_ALL(d,n) \
	for (d=descriptor_list,n=((d!=NULL) ? d->next : NULL); \
	     d; \
	     d=n,n=((n!=NULL) ? n->next : NULL))

#define MALLOC(result, type, number, where) do { \
	if (!((result)=(type *) XMALLOC (((number) * sizeof (type)), where))) \
		panic("Out of memory", 1);				\
	} while (0)

#endif