diff -urpP src_old/Makefile.lnx src/Makefile.lnx --- src_old/Makefile.lnx Sat Feb 15 14:17:43 1997 +++ src/Makefile.lnx Fri Jan 28 21:23:11 2000 @@ -7,11 +7,11 @@ DEBUG = -g NOCRYPT = O_FLAGS = C_FLAGS = $(O_FLAGS) -Wall -DLINUX2 $(DEBUG) $(PROF) $(NOCRYPT) -L_FLAGS = $(O_FLAGS) $(DEBUG) $(PROF) +L_FLAGS = $(O_FLAGS) $(DEBUG) $(PROF) -lz -O_FILES = act_comm.o act_info.o act_move.o act_obj.o act_wiz.o comm.o const.o \ - db.o fight.o handler.o interp.o magic.o save.o ssm.o special.o \ - update.o +O_FILES = act_comm.o act_info.o act_move.o act_obj.o act_wiz.o comm.o \ + const.o db.o fight.o handler.o interp.o magic.o mccp.o save.o \ + ssm.o special.o update.o envy: $(O_FILES) rm -f envy diff -urpP src_old/comm.c src/comm.c --- src_old/comm.c Sat Feb 15 14:17:43 1997 +++ src/comm.c Fri Jan 28 23:07:00 2000 @@ -135,6 +135,10 @@ extern int malloc_verify args( ( void ) const char echo_off_str [] = { '\0' }; const char echo_on_str [] = { '\0' }; const char go_ahead_str [] = { '\0' }; +const char compress_will [] = { '\0' }; +const char compress_do [] = { '\0' }; +const char compress_dont [] = { '\0' }; +const char compress_start [] = { '\0' }; #endif #if defined( unix ) || defined( AmigaTCP ) @@ -146,6 +150,11 @@ const char go_ahead_str [] = { '\0' }; const char echo_off_str [] = { IAC, WILL, TELOPT_ECHO, '\0' }; const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, '\0' }; const char go_ahead_str [] = { IAC, GA, '\0' }; + +/* mccp: compression negotiation strings */ +const char compress_will [] = { IAC, WILL, TELOPT_COMPRESS, '\0' }; +const char compress_do [] = { IAC, DO, TELOPT_COMPRESS, '\0' }; +const char compress_dont [] = { IAC, DONT, TELOPT_COMPRESS, '\0' }; #endif @@ -356,7 +358,8 @@ time_t current_time; /* Time of thi #if defined( macintosh ) void game_loop_mac_msdos args( ( void ) ); bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) ); -bool write_to_descriptor args( ( int desc, char *txt, int length ) ); +bool write_to_descriptor args( ( DESCRIPTOR_DATA *d, char *txt, int length ) ); +bool write_to_descriptor_2 args( ( int desc, char *txt, int length ) ); #endif #if defined( unix ) || defined( AmigaTCP ) || defined( WIN32 ) @@ -364,7 +367,8 @@ void game_loop_unix args( ( int control int init_socket args( ( u_short port ) ); void new_descriptor args( ( int control ) ); bool read_from_descriptor args( ( DESCRIPTOR_DATA *d ) ); -bool write_to_descriptor args( ( int desc, char *txt, int length ) ); +bool write_to_descriptor args( ( DESCRIPTOR_DATA *d, char *txt, int length ) ); +bool write_to_descriptor_2 args( ( int desc, char *txt, int length ) ); #endif @@ -609,6 +613,10 @@ void game_loop_mac_msdos( void ) /* * Send the greeting. */ + + /* mccp: tell the client we support compression */ + write_to_buffer( dnew, compress_will, 0 ); + { extern char * help_greeting; if ( help_greeting[0] == '.' ) @@ -865,10 +872,18 @@ void game_loop_unix( int control ) { d_next = d->next; - if ( ( d->fcommand || d->outtop > 0 ) + if ( ( d->fcommand || d->outtop > 0 || d->out_compress ) && FD_ISSET( d->descriptor, &out_set ) ) - { - if ( !process_output( d, TRUE ) ) + { + bool ok = TRUE; + + if ( d->fcommand || d->outtop > 0 ) + ok = process_output( d, TRUE ); + + if (ok && d->out_compress) + ok = processCompressed(d); + + if (!ok) { if ( d->character ) save_char_obj( d->character ); @@ -1050,7 +1065,7 @@ void new_descriptor( int control ) { if ( !str_suffix( pban->name, dnew->host ) ) { - write_to_descriptor( desc, + write_to_descriptor( dnew, "Your site has been banned from this Mud.\n\r", 0 ); #if !defined( WIN32 ) close( desc ); @@ -1074,6 +1089,9 @@ void new_descriptor( int control ) /* * Send the greeting. */ + + /* mccp: tell the client we support compression */ + write_to_buffer( dnew, compress_will, 0 ); { extern char * help_greeting; @@ -1146,6 +1164,13 @@ void close_socket( DESCRIPTOR_DATA *dclo bug( "Close_socket: dclose not found.", 0 ); } + if (dclose->out_compress) { + deflateEnd(dclose->out_compress); + free_mem(dclose->out_compress_buf, COMPRESS_BUF_SIZE); + free_mem(dclose->out_compress, sizeof(z_stream)); + } + + #if !defined( WIN32 ) close( dclose->descriptor ); #else @@ -1180,7 +1205,7 @@ bool read_from_descriptor( DESCRIPTOR_DA { sprintf( log_buf, "%s input overflow!", d->host ); log_string( log_buf ); - write_to_descriptor( d->descriptor, + write_to_descriptor( d, "\n\r*** PUT A LID ON IT!!! ***\n\r", 0 ); return FALSE; } @@ -1278,7 +1303,7 @@ void read_from_buffer( DESCRIPTOR_DATA * { if ( k >= MAX_INPUT_LENGTH - 2 ) { - write_to_descriptor( d->descriptor, "Line too long.\n\r", 0 ); + write_to_descriptor( d, "Line too long.\n\r", 0 ); /* skip the rest of the line */ for ( ; d->inbuf[i] != '\0'; i++ ) @@ -1295,6 +1320,16 @@ void read_from_buffer( DESCRIPTOR_DATA * --k; else if ( isascii( d->inbuf[i] ) && isprint( d->inbuf[i] ) ) d->incomm[k++] = d->inbuf[i]; + else if (d->inbuf[i] == (char) IAC) { + if (!memcmp(&d->inbuf[i], compress_do, strlen(compress_do))) { + i += strlen(compress_do) - 1; + compressStart(d); + } + else if (!memcmp(&d->inbuf[i], compress_dont, strlen(compress_dont))) { + i += strlen(compress_dont) - 1; + compressEnd(d); + } + } } /* @@ -1319,7 +1354,7 @@ void read_from_buffer( DESCRIPTOR_DATA * { sprintf( log_buf, "%s input spamming!", d->host ); log_string( log_buf ); - write_to_descriptor( d->descriptor, + write_to_descriptor( d, "\n\r*** PUT A LID ON IT!!! ***\n\r", 0 ); strcpy( d->incomm, "quit" ); } @@ -1397,7 +1432,7 @@ bool process_output( DESCRIPTOR_DATA *d, /* * OS-dependent output. */ - if ( !write_to_descriptor( d->descriptor, d->outbuf, d->outtop ) ) + if ( !write_to_descriptor( d, d->outbuf, d->outtop ) ) { d->outtop = 0; return FALSE; @@ -1571,7 +1606,7 @@ void write_to_buffer( DESCRIPTOR_DATA *d * If this gives errors on very long blocks (like 'ofind all'), * try lowering the max block size. */ -bool write_to_descriptor( int desc, char *txt, int length ) +bool write_to_descriptor_2( int desc, char *txt, int length ) { int iStart; int nWrite; @@ -1599,8 +1634,15 @@ bool write_to_descriptor( int desc, char return TRUE; } - - +/* mccp: write_to_descriptor wrapper */ +bool write_to_descriptor(DESCRIPTOR_DATA *d, char *txt, int length) +{ + if (d->out_compress) + return writeCompressed(d, txt, length); + else + return write_to_descriptor_2(d->descriptor, txt, length); +} + /* * Deal with sockets that haven't logged in yet. */ @@ -2536,4 +2578,3 @@ void gettimeofday( struct timeval *tp, v tp->tv_usec = 0; } #endif - diff -urpP src_old/interp.c src/interp.c --- src_old/interp.c Sat Feb 15 14:17:43 1997 +++ src/interp.c Fri Jan 28 21:24:05 2000 @@ -151,6 +151,7 @@ const struct cmd_type cmd_table [ ] = { "brief", do_brief, POS_DEAD, 0, LOG_NORMAL }, { "channels", do_channels, POS_DEAD, 0, LOG_NORMAL }, { "combine", do_combine, POS_DEAD, 0, LOG_NORMAL }, + { "compress", do_compress, POS_DEAD, 0, LOG_NORMAL }, { "config", do_config, POS_DEAD, 0, LOG_NORMAL }, { "description", do_description, POS_DEAD, 0, LOG_NORMAL }, { "password", do_password, POS_DEAD, 0, LOG_NEVER }, diff -urpP src_old/mccp.c src/mccp.c --- src_old/mccp.c Wed Dec 31 19:00:00 1969 +++ src/mccp.c Fri Jan 28 21:49:21 2000 @@ -0,0 +1,205 @@ +/* + * mccp.c - support functions for mccp (the Mud Client Compression Protocol) + * + * see http://homepages.ihug.co.nz/~icecube/compress/ and README.Rom24-mccp + * + * Copyright (c) 1999, Oliver Jowett . + * + * This code may be freely distributed and used if this copyright notice is + * retained intact. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "merc.h" + +char compress_start [] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, '\0' }; + +bool processCompressed(DESCRIPTOR_DATA *desc); +bool write_to_descriptor args( ( DESCRIPTOR_DATA *d, char *txt, int length ) ); + +/* + * Memory management - zlib uses these hooks to allocate and free memory + * it needs + */ + +void *zlib_alloc(void *opaque, unsigned int items, unsigned int size) +{ + return calloc(items, size); +} + +void zlib_free(void *opaque, void *address) +{ + free(address); +} + +/* + * Begin compressing data on `desc' + */ +bool compressStart(DESCRIPTOR_DATA *desc) +{ + z_stream *s; + + if (desc->out_compress) /* already compressing */ + return TRUE; + + /* allocate and init stream, buffer */ + s = (z_stream *)alloc_mem(sizeof(*s)); + desc->out_compress_buf = (unsigned char *)alloc_mem(COMPRESS_BUF_SIZE); + + s->next_in = NULL; + s->avail_in = 0; + + s->next_out = desc->out_compress_buf; + s->avail_out = COMPRESS_BUF_SIZE; + + s->zalloc = zlib_alloc; + s->zfree = zlib_free; + s->opaque = NULL; + + if (deflateInit(s, 9) != Z_OK) { + /* problems with zlib, try to clean up */ + free_mem(desc->out_compress_buf, COMPRESS_BUF_SIZE); + free_mem(s, sizeof(z_stream)); + return FALSE; + } + + write_to_descriptor(desc, compress_start, strlen(compress_start)); + + /* now we're compressing */ + desc->out_compress = s; + return TRUE; +} + +/* Cleanly shut down compression on `desc' */ +bool compressEnd(DESCRIPTOR_DATA *desc) +{ + unsigned char dummy[1]; + + if (!desc->out_compress) + return TRUE; + + desc->out_compress->avail_in = 0; + desc->out_compress->next_in = dummy; + + /* No terminating signature is needed - receiver will get Z_STREAM_END */ + + if (deflate(desc->out_compress, Z_FINISH) != Z_STREAM_END) + return FALSE; + + if (!processCompressed(desc)) /* try to send any residual data */ + return FALSE; + + deflateEnd(desc->out_compress); + free_mem(desc->out_compress_buf, COMPRESS_BUF_SIZE); + free_mem(desc->out_compress, sizeof(z_stream)); + desc->out_compress = NULL; + desc->out_compress_buf = NULL; + + return TRUE; +} + +/* Try to send any pending compressed-but-not-sent data in `desc' */ +bool processCompressed(DESCRIPTOR_DATA *desc) +{ + int iStart, nBlock, nWrite, len; + + if (!desc->out_compress) + return TRUE; + + /* Try to write out some data.. */ + len = desc->out_compress->next_out - desc->out_compress_buf; + if (len > 0) { + /* we have some data to write */ + + for (iStart = 0; iStart < len; iStart += nWrite) + { + nBlock = UMIN (len - iStart, 4096); + if ((nWrite = write (desc->descriptor, desc->out_compress_buf + iStart, nBlock)) < 0) + { + if (errno == EAGAIN || + errno == ENOSR) + break; + + return FALSE; /* write error */ + } + + if (nWrite <= 0) + break; + } + + if (iStart) { + /* We wrote "iStart" bytes */ + if (iStart < len) + memmove(desc->out_compress_buf, desc->out_compress_buf+iStart, len - iStart); + + desc->out_compress->next_out = desc->out_compress_buf + len - iStart; + } + } + + return TRUE; +} + +/* write_to_descriptor, the compressed case */ +bool writeCompressed(DESCRIPTOR_DATA *desc, char *txt, int length) +{ + z_stream *s = desc->out_compress; + + s->next_in = (unsigned char *)txt; + s->avail_in = length; + + while (s->avail_in) { + s->avail_out = COMPRESS_BUF_SIZE - (s->next_out - desc->out_compress_buf); + + if (s->avail_out) { + int status = deflate(s, Z_SYNC_FLUSH); + + if (status != Z_OK) { + /* Boom */ + return FALSE; + } + } + + /* Try to write out some data.. */ + if (!processCompressed(desc)) + return FALSE; + + /* loop */ + } + + /* Done. */ + return TRUE; +} + +/* User-level compression toggle */ +void do_compress( CHAR_DATA *ch, char *argument ) +{ + if (!ch->desc) { + send_to_char("What descriptor?!\n", ch); + return; + } + + if (!ch->desc->out_compress) { + if (!compressStart(ch->desc)) { + send_to_char("Failed.\n", ch); + return; + } + + send_to_char("Ok, compression enabled.\n", ch); + } else { + if (!compressEnd(ch->desc)) { + send_to_char("Failed.\n", ch); + return; + } + + send_to_char("Ok, compression disabled.\n", ch); + } +} diff -urpP src_old/merc.h src/merc.h --- src_old/merc.h Sat Feb 15 14:17:43 1997 +++ src/merc.h Fri Jan 28 21:45:41 2000 @@ -43,7 +43,13 @@ #define DECLARE_GAME_FUN( fun ) GAME_FUN fun #endif +/* mccp: support bits */ +#include + +#define TELOPT_COMPRESS 85 + +#define COMPRESS_BUF_SIZE 16384 /* * Short scalar types. @@ -296,10 +302,13 @@ struct descriptor_data char * outbuf; int outsize; int outtop; -}; - + /* mccp: support data */ + z_stream * out_compress; + unsigned char * out_compress_buf; +}; + /* * Attribute bonus structures. */ @@ -1425,6 +1434,7 @@ DECLARE_DO_FUN( do_close ); DECLARE_DO_FUN( do_combine ); DECLARE_DO_FUN( do_commands ); DECLARE_DO_FUN( do_compare ); +DECLARE_DO_FUN( do_compress ); /* MCCP */ DECLARE_DO_FUN( do_config ); DECLARE_DO_FUN( do_consider ); DECLARE_DO_FUN( do_credits ); @@ -2038,6 +2048,12 @@ void gain_exp args( ( CHAR_DATA *ch, int void gain_condition args( ( CHAR_DATA *ch, int iCond, int value ) ); void update_handler args( ( void ) ); void ban_update args( ( void ) ); + +/* mccp.c */ +bool compressStart(DESCRIPTOR_DATA *desc); +bool compressEnd(DESCRIPTOR_DATA *desc); +bool processCompressed(DESCRIPTOR_DATA *desc); +bool writeCompressed(DESCRIPTOR_DATA *desc, char *txt, int length); #undef CD #undef MID