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