/* * 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