/* * IMC2 Liberty Server - Developed by Mud Domain. * Copyright (C)2004-2008 Roger Libiez(Samson) * Additional code Copyright (C)2004-2006 by Jonathan Walker (Xorith) * Comments and suggestions welcome: imc@intermud.us * Registered with the United States Copyright Office: TX 5-953-618 * * IMC2 MUD-Net versions 3.20 through 3.31 developed by Mud Domain. * Copyright (C) 2003-2004 Roger Libiez (Samson) * Additional code Copyright (C) 2003-2004 by Jonathan Walker (Xorith) * * Some portions of code from Hermes 3.17 Copyright (C)2003 Rogel * * IMC2 Hermes version 3.15 is developed by Rogel * Copyright (C) 2003 Rogel * * IMC2 MUD-Net versions 3.00 through 3.10 developed by Alsherok and Crimson Oracles * Copyright (C) 2002-2003 Roger Libiez (Samson) * Additional code Copyright (C) 2002 Orion Elder * Registered with the United States Copyright Office: TX 5-555-584 * * IMC2 Gold versions 1.00 through 2.00 developed by MudWorld. * Copyright (C) 1999 - 2002 * Scion Altera, Shogar, Kratas, Tagith, Noplex, * Senir, Trax, Samson, and Ntanel StormBlade( Anthony R. Haslage ) * * IMC2 version 0.10 - an inter-mud communications protocol * Copyright (C) 1996 & 1997 Oliver Jowett <oliver@randomly.org> * * 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. * */ #define IMC_VERSIONID "IMC2 Liberty SV-2.1 Server" #define IMC_CHANNEL_FILE "../config/iced" #define IMC_CONFIG_FILE "../config/config" #define IMC_BAN_FILE "../config/ban" #define LOG_DIR "../logs" #define IMC_UPDATE_FILE "../update" #define IMC_BOOT_FILE "../bootme" #define IMC_HBOOT_FILE "../hotbootme" #define IMC_DUMP_FILE "../html/infodump" #define HOTBOOT_FILE "../config/hotboot" #define EXE_FILE "server" #define REMINFO_FILE "../config/reminfo" #define LASTON_FILE "../config/laston" /* * Memory allocation macros. */ #define CREATE(result, type, number) \ do \ { \ if (!((result) = (type *) calloc ((number), sizeof(type)))) \ { \ perror("malloc failure"); \ fprintf(stderr, "Malloc failure @ %s:%d\n", __FILE__, __LINE__ ); \ abort(); \ } \ } while(0) #define DISPOSE(point) \ do \ { \ if((point)) \ { \ free((point)); \ (point) = NULL; \ } \ } while(0) /* Less tweakable parameters - only change these if you know what they do */ /* number of packets to remember at a time */ const int IMC_MEMORY = 256; /* start dropping really old packets based on this figure */ const int IMC_PACKET_LIFETIME = 60; /* maximum time spent in getting a connection to a remote mud */ const int IMC_LOGIN_TIMEOUT = 120; /* min input/output buffer size */ const int IMC_MINBUF = 256; /* max input/output buffer size */ const int 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 */ const int IMC_PACKET_LENGTH = 16300; /* max length of a data type (estimate) (max length equal to 15,938 by default) * Had to hard set this because the other variables are now gone */ const int IMC_DATA_LENGTH = 15938; /* String Defines - Used to set lengths of numerous string arrays in code */ /* Should be no need to change these. */ /* Large String Size */ const int LSS = 4096; /* Medium String Size */ const int MSS = 1024; /* Small String Size */ const int SSS = 256; /* String Comparison Macros - Rogel */ #define STR_CEQL(a,b) (strcasecmp ((a), (b)) == 0) #define STRN_CEQL(a,b,n) (strncasecmp ((a), (b), (n)) == 0) /* Predeclarations */ class imc_packet; struct imc_info; /* Connection states */ enum connection_states{ CONN_NONE, CONN_SERVERCONNECT, CONN_WAITCLIENTPWD, CONN_WAITSERVERPWD, CONN_COMPLETE }; /* Channel access levels */ enum channel_access_levels{ ACCESS_NONE, ACCESS_CREATOR, ACCESS_OPERATOR, ACCESS_OWNER }; /* Channel permissions */ enum channel_perms{ PERM_MORT, PERM_IMM, PERM_ADMIN, PERM_IMP }; typedef void PACKET_FUN( imc_packet *q, string packet ); #define PFUN( name ) extern "C" void (name)( imc_packet *q, string packet ) struct imc_laston { string name; string chan; time_t last_time; }; struct imc_channel { string name; /* name of channel */ string owner; /* owner (singular) of channel */ string operators; /* current operators of channel */ string invited; string excluded; string active; string level; /* The default level you want this channel to refresh at on supporting clients */ string lname; /* Default localname for this channel */ bool open; }; struct imc_rcmd_table { string name; void (*cmdfn)( const string &, const string & ); bool need_data; }; const int MAX_REMOTE_COMMAND = 22; extern const struct imc_rcmd_table imc_remote_cmdtable[MAX_REMOTE_COMMAND]; struct iced_cmd_table { string name; unsigned char level; /* 0=anyone, 1=op only, 2=owner only */ void (*cmdfn)( imc_channel *c, const string &, const string &, const string & ); bool need_data; }; const int MAX_ICED_COMMAND = 12; extern const struct iced_cmd_table iced_cmdtable[MAX_ICED_COMMAND]; /* an actual IMC connection */ struct connection { imc_info *info; /* imc_info struct for this connection */ string host; /* The IP this connection came from */ char *inbuf; /* input buffer */ char *outbuf; /* output buffer */ char *deflate_buf; char *inflate_buf; unsigned long auth_value; /* Used for MD5 authentication */ int desc; /* descriptor */ int insize; int outsize; unsigned short state; /* IMC_xxxx state */ unsigned short version; /* version of remote site */ bool is_compressing; /* Have we initiated compression? */ bool newoutput; /* try to write at end of cycle regardless of fd_set state? */ bool disconnect; /* Should this connection be closed? */ }; /* an IMC packet, as seen by the high-level code */ class imc_packet { public: imc_packet(); imc_packet( const string &, const string &, const string & ); void forward(); void writepacket( connection *c ); string to; /* destination of packet */ string from; /* source of packet */ string type; /* type of packet */ bool stop; /* Stops flagged packets from forwarding */ ostringstream data; /* packet data fields */ /* internal things which only the low-level code needs to know about */ struct { string to; string from; string path; unsigned long sequence; } i; }; /* a configured IMC connection */ struct imc_info { connection *conn; /* Points to the connection struct for this mud */ string name; /* name of remote mud */ string host; /* hostname */ string url; /* Not saved - for webstats stuff */ string serverpw; /* server password */ string clientpw; /* client password */ time_t last_connected; /* last connected when? */ time_t login_time; /* Initial connection time for this boot */ bool server; /* Is this another server? */ bool md5; /* Is this connection using MD5? */ bool sha256; /* Is this connection using SHA-256? */ unsigned short port; /* remote port */ }; /* IMC statistics */ struct imc_statistics { time_t start; /* when statistics started */ 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 long rx_cmpbytes; /* Compressed bytes received */ unsigned long tx_cmpbytes; /* Compressed bytes sent */ long rx_bytessaved; /* How much have we saved? */ long tx_bytessaved; unsigned int max_pkt; /* Max. size packet processed */ unsigned int sequence_drops; /* Dropped packets due to age */ }; /* info about another mud on IMC */ struct imc_reminfo { string name; string version; string url; string path; string network; string host; string port; unsigned long top_sequence; bool expired; bool sha256; /* Set by other servers to enforce remote admin security */ }; /* an entry in the memory table */ struct imc_memory { string from; unsigned long sequence; }; /* an event */ struct imc_event { struct imc_event *next; void (*callback)( const void *data ); const void *data; time_t when; }; /* site information */ struct imc_siteinfo { string name; /* Name of the Server */ string chancreators; /* People allowed to create channels */ string serveradmins; /* People allowed to use remote administration */ string serveradminpwd; /* Password used for MD5 authentiaction of remote commands */ string host; /* hostname or ip address */ string network; /* Name of the network your server is on */ string url; /* URL used for webstats script on other servers */ string statsfile; /* Holds the directory to use for the statdump file */ unsigned long bind; /* IP Address to bind to if needed */ unsigned int connects; /* Number of connections */ unsigned int maxconnects; /* Maximum allowed connections */ short port; /* Port the server listens on */ bool autoupdate; /* Does this server use the autoupdate feature? */ bool webstats; /* Does this server use the webstats dump feature? */ bool priv; /* Is this a private server? */ bool prune; /* Does this server self-clean outdated connections? */ bool remoteadmin; /* Does this server allow for remote administration? */ bool can_compress; /* Does this server have zlib access? */ }; struct packet_handler { PACKET_FUN *func; string name; }; extern time_t imc_now; /* This stream wrapper class was graciously provided by Ksilyan and Nick Gammon. * Opens a logfile stream which can be written to as follows: * logfile << __FUNCTION__ << "Text here" << some numbers, variables, etc here << endl; */ class StreamWrapper { protected: ostream* stream_; public: StreamWrapper() : stream_( NULL ) { } void setStream( ostream& stream ) { stream_ = &stream; } ostream& getStream() { return *stream_; } template<class ParamType> ostream& operator << ( ParamType param ) { char *strtime; strtime = ctime( &imc_now ); strtime[strlen(strtime)-1] = '\0'; (*stream_) << strtime << " :: " << param; return *stream_; } }; void imc_add_event( int when, void (*callback)( const void *), const void *data ); void imc_cancel_event( void (*callback)( const void *), const void *data ); int imc_next_event( void (*callback)( const void *), const void *data ); int imc_get_event_timeout( void ); void imc_run_events( time_t newtime ); void ev_close_notify( const void *data ); void ev_login_timeout( const void *data ); void ev_reconnect( const void *data ); void ev_iced_refresh( const void *data ); void ev_mudconnections( const void *data ); void ev_purgeinfo( const void *data ); void ev_statdump( const void *data ); void ev_keepalive( const void *data ); void ev_bootcheck( const void *data ); void forward( imc_packet *p ); void imc_recv( imc_packet *p ); bool imc_connect_to( const string& mud ); void imc_send_emote( int channel, const string& argument, const string& to ); void imc_send_tell( const string& to, const string& argument ); void imc_send_whoreply( const string& to, const string& data ); void imc_send_pingreply( const string& to, const string& path ); void send_reminfo_destroy( const string& mudname ); bool imc_saveconfig( void ); void iced_save_channels( void ); void imc_savebans( void ); void imc_hotboot( void ); void do_close( connection *c ); void imc_shutdown( void ); template< typename T > void deleteptr( T* & ptr ) { delete ptr; ptr = NULL; }