/* * IMC2 version 0.10 - an inter-mud communications protocol * Copyright (C) 1996 & 1997 Oliver Jowett <oliver@randomly.org> * * IMC2 Gold versions 1.00 though 2.00 were developed by MudWorld. * Copyright (C) 1999 - 2002 Haslage Net Electronics (Anthony R. Haslage) * * IMC2 MUD-Net version 3.10 was developed by Alsherok and Crimson Oracles * Copyright (C) 2002 Roger Libiez ( Samson ) * Additional code Copyright (C) 2002 Orion Elder * Registered with the United States Copyright Office * TX 5-555-584 * * IMC2 Hermes R01-R04 were developed by Rogel * Copyright (C) 2003-2004 by Rogel * * IMC2 Cyclone R01 was developed by Rogel * Copyright (C) 2004 by Rogel * * 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. * */ /* This is the protocol version */ #define IMC_VERSION 2 #define IMC_VERSIONID "IMC2 R-01 Cyclone Bridge" #define IMC_CONFIG_FILE "./config" /* * Memory allocation macros. */ #define CREATE(result, type, number) \ do \ { \ if (!((result) = (type *) calloc ((number), sizeof(type)))) \ { \ perror("malloc failure"); \ Log("Malloc failure @ %s:%d\n", __FILE__, __LINE__ ); \ abort(); \ } \ } while(0) #define DISPOSE(point) \ do \ { \ if (!(point)) \ { \ Log( "Freeing null pointer @ %s:%d\n", __FILE__, __LINE__ ); \ } \ else \ { \ free((point)); \ (point) = NULL; \ } \ } while(0) /* double-linked list handling macros -Thoric ( From the Smaug codebase ) */ /* Updated by Scion 8/6/1999 */ #define LINK(link, first, last, next, prev) \ do \ { \ if ( !(first) ) \ { \ (first) = (link); \ (last) = (link); \ } \ else \ (last)->next = (link); \ (link)->next = NULL; \ if (first == link) \ (link)->prev = NULL; \ else \ (link)->prev = (last); \ (last) = (link); \ } while(0) #define INSERT(link, insert, first, next, prev) \ do \ { \ (link)->prev = (insert)->prev; \ if ( !(insert)->prev ) \ (first) = (link); \ else \ (insert)->prev->next = (link); \ (insert)->prev = (link); \ (link)->next = (insert); \ } while(0) #define UNLINK(link, first, last, next, prev) \ do \ { \ if ( !(link)->prev ) \ { \ (first) = (link)->next; \ if ((first)) \ (first)->prev = NULL; \ } \ else \ { \ (link)->prev->next = (link)->next; \ } \ if ( !(link)->next ) \ { \ (last) = (link)->prev; \ if ((last)) \ (last)->next = NULL; \ } \ else \ { \ (link)->next->prev = (link)->prev; \ } \ } while(0) /* Less tweakable parameters - only change these if you know what they do */ /* number of packets to remember at a time */ #define IMC_MEMORY 256 /* start dropping really old packets based on this figure */ #define IMC_PACKET_LIFETIME 60 /* maximum time spent in getting a connection to a remote mud */ #define IMC_LOGIN_TIMEOUT 120 /* min input/output buffer size */ #define IMC_MINBUF 256 /* max input/output buffer size */ #define IMC_MAXBUF 16384 /* Changing these defines impacts the protocol itself - other muds may drop your * packets if you get this wrong */ /* max length of any packet */ #define IMC_PACKET_LENGTH 16300 /* max length of any mud name */ #define IMC_MNAME_LENGTH 20 /* max length of any player name */ #define IMC_PNAME_LENGTH 40 /* max length of any player@mud name */ #define IMC_NAME_LENGTH (IMC_MNAME_LENGTH+IMC_PNAME_LENGTH+1) /* max length of a path */ #define IMC_PATH_LENGTH 200 /* max length of a packet type */ #define IMC_TYPE_LENGTH 20 /* max length of a password */ #define IMC_PW_LENGTH 20 /* max length of a data type (estimate) (max length equal to 15,938 by default) */ #define IMC_DATA_LENGTH (IMC_PACKET_LENGTH-2*IMC_NAME_LENGTH-IMC_PATH_LENGTH-IMC_TYPE_LENGTH-20) /* max number of data keys in a packet */ #define IMC_MAX_KEYS 20 /* connection states */ enum{ CONN_NONE, CONN_SERVERCONNECT, CONN_WAITSERVERPWD, CONN_COMPLETE } connection_states; /* String Defines - Used to set lengths of numerous string arrays in code */ /* Should be no need to change these. */ // Large String Size #define LSS 4096 // Medium String Size #define MSS 1024 // Small String Size #define SSS 256 /* Macro taken from DOTD codebase. Fcloses a file, then nulls its pointer for safety. */ #define SFCLOSE(fp) fclose(fp); fp=NULL; #if !defined(FALSE) || !defined(TRUE) typedef enum { FALSE, TRUE } bool; #endif /* String Comparison Macros */ #define STR_EQL(a,b) (strcmp ((a), (b)) == 0) #define STR_CEQL(a,b) (strcasecmp ((a), (b)) == 0) #define STRN_EQL(a,b,n) (strncmp ((a), (b), (n)) == 0) #define STRN_CEQL(a,b,n) (strncasecmp ((a), (b), (n)) == 0) /* typedefs */ typedef struct imc_connect CONNECTION; typedef struct imc_network NETWORK; typedef struct imc_affiliate AFFILIATE; typedef struct imc_reminfo REMINFO; typedef struct imc_packet PACKET; typedef struct imc_channel CHANNEL; extern CONNECTION *first_connection; extern CONNECTION *last_connection; extern NETWORK *first_network; extern NETWORK *last_network; extern REMINFO *first_reminfo; extern REMINFO *last_reminfo; extern CHANNEL *first_channel; extern CHANNEL *last_channel; /* an IMC packet, as seen by the high-level code */ struct imc_packet { char to[IMC_NAME_LENGTH]; /* destination of packet */ char from[IMC_NAME_LENGTH]; /* source of packet */ char type[IMC_TYPE_LENGTH]; /* type of packet */ char *key[IMC_MAX_KEYS]; char *value[IMC_MAX_KEYS]; /* internal things which only the low-level code needs to know about */ struct { char to[IMC_NAME_LENGTH]; char from[IMC_NAME_LENGTH]; char path[IMC_PATH_LENGTH]; unsigned long sequence; } i; }; /* an actual IMC connection */ struct imc_connect { CONNECTION *next; CONNECTION *prev; AFFILIATE *affiliate; /* network affiliate that we are posing as */ int desc; /* descriptor */ unsigned short state; /* IMC_xxxx state */ unsigned short version; /* version of remote site */ bool newoutput; /* try to write at end of cycle regardless of fd_set state? */ char *inbuf; /* input buffer */ unsigned int insize; char *outbuf; /* output buffer */ unsigned int outsize; char *ip; /* IP of connection */ }; /* a network listing */ struct imc_network { NETWORK *next; NETWORK *prev; char *netname; /* name of network */ char *host; /* hostname */ unsigned short port; /* remote port */ char *serverpw; /* server password */ char *clientpw; /* client password */ char *blacklist; /* list of people/muds blacklisted from sending to this network */ AFFILIATE *first_affiliate; AFFILIATE *last_affiliate; }; /* a network's affiliate */ struct imc_affiliate { AFFILIATE *next; AFFILIATE *prev; char *name; /* Name of the affiliate */ NETWORK *network; /* Network affiliated to */ AFFILIATE *equiv; /* Equivalent info for affiliate's record of this connection */ CONNECTION *connection; /* Affiliate's connection to the network */ bool full_bridge; /* Pass network listings through? */ }; /* channel information */ struct imc_channel { CHANNEL *next; CHANNEL *prev; char *local_channels; }; /* IMC statistics */ typedef struct { unsigned long rx_pkts; /* Received packets */ unsigned long tx_pkts; /* Transmitted packets */ unsigned long rx_bytes; /* Received bytes */ unsigned long tx_bytes; /* Transmitted bytes */ unsigned int max_pkt; /* Max. size packet processed */ unsigned int sequence_drops; /* Dropped packets due to age */ } imc_statistics; /* info about another mud on IMC */ struct imc_reminfo { REMINFO *next; REMINFO *prev; NETWORK *network; char *name; char *netname; char *web; char *version; char *path; unsigned long top_sequence; }; struct imc_keepalive { REMINFO *remote; char destination[IMC_MNAME_LENGTH]; unsigned int count; AFFILIATE *affiliate; }; /* an event */ typedef struct _imc_event { time_t when; void (*callback)(void *data); void *data; struct _imc_event *next; } imc_event; /* for the versioning table */ typedef struct { unsigned char version; char *(*generate) (PACKET *, AFFILIATE *); PACKET *(*interpret) (const char *); } _imc_vinfo; /* an entry in the memory table */ typedef struct { char *from; AFFILIATE *affiliate; unsigned long sequence; } _imc_memory; /* data structures */ /* the packet memory table */ extern _imc_memory imc_memory[IMC_MEMORY]; /* the version lookup table */ extern _imc_vinfo imc_vinfo[]; /* global stats struct */ extern imc_statistics imc_stats; /* the event list, and recycle list */ extern imc_event *imc_event_list, *imc_event_free; /* the current time */ extern time_t imc_now; /* next sequence number to use */ extern unsigned long imc_sequencenumber; /* main loop for bridge */ void bridge_loop( struct timeval last_time ); /* Logging */ void Log( const char *format, ... ); /* event handling */ void imc_add_event( int when, void (*callback)(void *), void *data ); void imc_cancel_event( void (*callback)(void *), void *data ); imc_event *imc_find_event(void (*callback)(void *), void *data); int imc_next_event( void (*callback)(void *), void *data ); unsigned int imc_get_event_timeout( void ); void imc_run_events(time_t newtime); void ev_close_notify( void *data ); void ev_login_timeout( void *data ); void ev_reconnect( void *data ); void ev_send_isalive( void *data ); void imc_send( PACKET *p, AFFILIATE *a ); void imc_recv( PACKET *p, AFFILIATE *a ); void imc_startup( void ); void imc_shutdown( void ); void imc_idle(unsigned int s); void imc_idle_select( fd_set *sread, fd_set *swrite, fd_set *exc, time_t now ); bool imc_connect_to( AFFILIATE *i ); void imc_send_tell( const char *to, const char *argument, AFFILIATE *a ); void imc_send_whoreply( const char *to, const char *data, AFFILIATE *a ); void imc_send_keepalive( REMINFO *r, char *destination, AFFILIATE *a ); void imc_send_pingreply( const char *to, const char *path, AFFILIATE *a ); void imc_recv_who( PACKET *p, const char *pname, const char *type, AFFILIATE *a ); bool imc_readconfig( void ); NETWORK *imc_new_network( void ); char *find_channel_equivalent( const char *from, NETWORK *from_network, NETWORK *to_network ); /* Event support functions */ void imc_request_keepalive( AFFILIATE *a );