ackmud/area/imc/
ackmud/npcs/a/
ackmud/npcs/c/
ackmud/npcs/d/
ackmud/npcs/e/
ackmud/npcs/f/
ackmud/npcs/h/
ackmud/npcs/i/
ackmud/npcs/k/
ackmud/npcs/l/
ackmud/npcs/n/
ackmud/npcs/o/
ackmud/npcs/p/
ackmud/npcs/r/
ackmud/npcs/s/
ackmud/npcs/w/
ackmud/player/c/
ackmud/player/z/
/*
 * IMC2 - an inter-mud communications protocol
 *
 * imc.h: the core protocol definitions
 *
 * Copyright (C) 1996 Oliver Jowett <oliver@sa-search.massey.ac.nz>
 *
 * 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 (see the file COPYING); if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifndef IMC_H
#define IMC_H

#include <sys/time.h>


/**  Configurable stuff  **/


/* system defines: #define NO_xxxx if your system doesn't support a function */

/* for memmove() */
#undef NO_MEMMOVE

/* for vsnprintf() (probably most non-linux systems) */
#undef NO_VSNPRINTF

/* for strerror() (eg. some versions of SunOS) */
#undef NO_STRERROR

/* for strtoul() */
#undef NO_STRTOUL

/* #define this if you aren't using gcc (or if __attribute__ isn't supported
 * for some other reason)
 */

#undef NO_ATTRIBUTE


/* IMC tweakable values */

/* maximum number of muds we know about (direct connections, not indirect) */
#define IMC_MAX    20

/* Increase the memory #defines if you start getting echoing */

/* number of packets to remember at a time */
#define IMC_MEMORY 500
/* how long until packets time out of the memory (seconds) */
#define IMC_MEMORY_TIMEOUT 900

/* Reconnection timeouts */

/* How often to try to reconnect (seconds) */
#define IMC_RECONNECT_TIME 1800
/* How soon the first reconnect attempt is (seconds) */
#define IMC_RECONNECT_TIME_1 120

/* Packet spam thresholds - these will need to be tweaked depending on
 * how often imc_ll_idle is called. Stock ROM/Envy will call it every
 * 250ms or thereabouts.
 */

/* counter 1: long-term threshold
 *            allow 0.5/second normally
 *            allow 2/second for up to 20s
 */
#define IMC_SPAM1SIZE 8
#define IMC_SPAM1LIMIT 240

/* counter 2: short-term threshold, catch bad spamming early
 *            allow 1/second normally
 *            allow 4/second for 5s
 */
#define IMC_SPAM2SIZE 4
#define IMC_SPAM2LIMIT 60



/** Less tweakable stuff - don't change this unless you understand it! **/

/* This is the protocol version */
#define IMC_VERSION 2
/* This is the code version ID (used in keepalives) */
#define IMC_VERSIONID "imc2-0.7a"

/* enable paranoia in packet forwarding (generally a Good Thing) */
#define IMC_PARANOIA

/* various buffer sizes */

#define IMC_BUFFER_SIZE   16384
#define IMC_PACKET_LENGTH 16300
#define IMC_MNAME_LENGTH  20
#define IMC_PNAME_LENGTH  40
#define IMC_NAME_LENGTH   (IMC_MNAME_LENGTH+IMC_PNAME_LENGTH)
#define IMC_PATH_LENGTH   200
#define IMC_TYPE_LENGTH   20
#define IMC_PW_LENGTH     20
#define IMC_DATA_LENGTH   (IMC_PACKET_LENGTH-2*IMC_NAME_LENGTH-IMC_PATH_LENGTH-IMC_TYPE_LENGTH-20)
#define IMC_MAX_KEYS      20



/** End of configurable section **/




/* Don't change below here unless you know what you're doing! */

/* handle system-specific #defines */

/* our version of memmove (ugly!) */
#ifdef NO_MEMMOVE
#define memmove(dest,src,size)              \
do {                                        \
  char *d=(char *)(dest), *s=(char *)(src); \
  int sz=(size);                            \
  if (d<s)                                  \
    for ( ; sz; --sz)                       \
      *d++=*s++;                            \
  else                                      \
    for (s+=sz,d+=sz; sz; --sz)             \
      *(--d)=*(--s);                        \
} while(0)
#endif

/* try strtol if we don't have strtoul */
#ifdef NO_STRTOUL
#define strtoul(p,e,b) ((unsigned long)strtol((p),(e),(b)))
#endif

/* fake a strerror if we don't have it - ick */
#ifdef NO_STRERROR
#define strerror(e) \
((e)==ECONNRESET   ? "Connection reset by peer" : \
 (e)==ENETUNREACH  ? "Network unreachable"      : \
 (e)==ETIMEDOUT    ? "Connection timed out"     : \
 (e)==ECONNREFUSED ? "Connection refused"       : \
 (e)==EHOSTUNREACH ? "No route to host"         : \
                     "Unknown error")
#endif

/* map vsnprintf to vsprintf if it isn't available (we lose some buffer
 * overflow protection in the logging fns, though)
 */

#ifdef NO_VSNPRINTF
#define vsnprintf(buf, len, fmt, ap) vsprintf(buf, fmt, ap)
#endif

/* nuke __attribute__ if it's not supported */

#ifdef NO_ATTRIBUTE
#define __attribute__(x) /*nothing*/
#endif

/* connection states */

#define IMC_CLOSED     0
#define IMC_CONNECTING 1
#define IMC_WAIT1      2
#define IMC_WAIT2      3
#define IMC_CONNECTED  4

/* mud flags */

#define IMC_NOAUTO 1
#define IMC_CLIENT 2
#define IMC_RECONNECT 4
#define IMC_BROADCAST 8
#define IMC_DENY 16

/* typedefs */

typedef struct
{
  char *key[IMC_MAX_KEYS];
  char *value[IMC_MAX_KEYS];
} imc_data;

typedef struct
{
  char to[IMC_NAME_LENGTH];	/* destination of packet */
  char from[IMC_NAME_LENGTH];	/* source of packet      */
  char type[IMC_TYPE_LENGTH];	/* type of packet        */
  imc_data data;		/* data of packet        */
} imc_packet;

typedef struct
{
  int desc;			/* descriptor */
  int info;			/* index into imc_info */
  int state;			/* IMC_xxxx state */
  int inuse;			/* in use? */
  int version;		        /* version of remote site */
  
  char *inbuf;		        /* input buffer */
  char *outbuf;		        /* output buffer */

  int spamcounter1;             /* packet spam counters */
  int spamcounter2;

} _imc;

typedef struct
{
  char *name;			/* name of remote mud */
  char *host;			/* hostname */
  int index;			/* index of connected descriptor */
  unsigned short port;		/* remote port */
  char *serverpw;		/* server password */
  char *clientpw;		/* client password */
  int connected;		/* fully connected? */
  int flags;			/* connection flags */
  time_t timer;		        /* time of next reconnect attempt */
  int inuse;                    /* this entry is in use? */

  int rcvstamp;                 /* packets get this stamp on arrival */
  int noforward;                /* packets with these bits set don't get
				 * forwarded here */
} _imc_info;

typedef struct
{
  time_t start;		        /* when statistics started */
  
  long rx_pkts;		        /* received packets */
  long tx_pkts;		        /* transmitted packets */
  long rx_bytes;		/* received bytes */
  long tx_bytes;		/* transmitted bytes */
} imc_statistics;

extern imc_statistics imc_stats;

typedef struct _imc_reminfo
{
  char *name;
  char *version;
  time_t alive;
  int ping;
  char *route;
  struct _imc_reminfo *next;
} imc_reminfo;

extern imc_reminfo *imc_remoteinfo;


/* internal stuff not exported outside IMC */
#ifdef IMC_INTERNALS

/* imc_internal is the internal packet representation */

typedef struct
{
  char to[IMC_NAME_LENGTH];
  char from[IMC_NAME_LENGTH];
  char path[IMC_PATH_LENGTH];
  char type[IMC_TYPE_LENGTH];
  imc_data data;
  unsigned long sequence;
  int stamp;
} imc_internal;

typedef struct
{
  int version;
  const char *(*generate) (const imc_internal *);
  imc_internal *(*interpret) (const char *);
} _imc_vinfo;

extern _imc_vinfo imc_vinfo[];

typedef struct
{
  char *from;
  unsigned long sequence;
  int timer;
} _imc_memory;

extern _imc_memory imc_memory[IMC_MEMORY];

#endif



/* data structures */

extern char *imc_name;
extern _imc imc[IMC_MAX];
extern _imc_info imc_info[IMC_MAX];
extern time_t imc_now;	/* set before calling imc_ll_idle */
extern unsigned long imc_sequencenumber;

/* exported functions */

/* imc data handlers */
const char *imc_getkey(const imc_data * p, const char *key, const char *def);
int imc_getkeyi(const imc_data * p, const char *key, int def);
void imc_addkey(imc_data * p, const char *key, const char *value);
void imc_addkeyi(imc_data * p, const char *key, int value);
void imc_initdata(imc_data * p);
void imc_freedata(imc_data * p);

/* reminfo handling */
imc_reminfo *imc_find_reminfo(const char *name);
imc_reminfo *imc_new_reminfo(void);
void imc_delete_reminfo(imc_reminfo * p);

/* other stuff */
void imc_send(const imc_packet * p);
int imc_ll_startup(const char *name, int port);
void imc_ll_shutdown(void);
void imc_ll_idle(void);
int imc_connect(const char *mud);
int imc_disconnect(const char *mud);

const char *imc_error(void);

const char *imc_flagname(int value);
int imc_flagvalue(const char *name);

int imc_getmud(const char *name);

const char *imc_nameof(const char *name);
const char *imc_mudof(const char *name);
const char *imc_makename(const char *name, const char *mud);
const char *imc_firstinpath(const char *path);
const char *imc_lastinpath(const char *path);
const char *imc_getarg(const char *arg, char *buf, int length);

void imc_recv(const imc_packet * p);
void imc_log(const char *string);
void imc_debug(int desc, int out, const char *packet);

void imc_logstring(const char *format,...) __attribute__((format(printf,1,2)));
void imc_logerror(const char *format,...) __attribute__((format(printf,1,2)));
void imc_qerror(const char *format,...) __attribute__((format(printf,1,2)));
void imc_lerror(const char *format,...) __attribute__((format(printf,1,2)));

void imc_slower(char *what);
void imc_sncpy(char *dest, const char *src, int count);
const char *imc_makename(const char *player, const char *mud);
int imc_getindex(const char *mud);
const char *imc_getdescname(int i);

/* memory allocation hooks
 * these aren't #defines so we don't have to know about the actual mud
 * function declarations in imc.c/imc-comm.c
 */

void *imc_malloc(int size);
void imc_free(void *block, int size);
char *imc_strdup(const char *src);
void imc_strfree(char *str);

#endif