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