diff -bBdNrw -U5 old/Makefile src/Makefile --- old/Makefile Tue Aug 21 15:01:46 2001 +++ src/Makefile Tue Aug 21 15:02:03 2001 @@ -1,15 +1,15 @@ CC = gcc PROF = NOCRYPT = C_FLAGS = -O -Wall -g -ggdb -Dlinux $(PROF) $(NOCRYPT) -L_FLAGS = -O $(PROF) +L_FLAGS = -O $(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 special.o update.o \ kav_info.o kav_fight.o kav_wiz.o clan.o mage.o rot_wiz.o \ - demon.o + demon.o mccp.o merc: $(O_FILES) rm -f merc $(CC) $(L_FLAGS) -o merc $(O_FILES) -lcrypt diff -bBdNrw -U5 old/comm.c src/comm.c --- old/comm.c Tue Aug 21 15:01:46 2001 +++ src/comm.c Tue Aug 21 15:09:03 2001 @@ -103,11 +103,14 @@ 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' }; #endif - +const char will_compress [] = { IAC, WILL, TELOPT_COMPRESS, '\0' }; +const char will_compress2 [] = { IAC, WILL, TELOPT_COMPRESS2, '\0' }; +bool compressStart args( ( DESCRIPTOR_DATA *d, unsigned char telopt ) ); +bool compressEnd args( ( DESCRIPTOR_DATA *d ) ); /* * OS-dependent declarations. */ #if defined(_AIX) @@ -306,19 +309,17 @@ * OS-dependent local functions. */ #if defined(macintosh) || defined(MSDOS) 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 ) ); #endif #if defined(unix) void game_loop_unix args( ( int control ) ); int init_socket args( ( int 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 ) ); #endif @@ -675,10 +676,35 @@ } } exit(1); } +void do_compress(CHAR_DATA *ch, char *argument) +{ + /* no socket, no compression */ + if (!ch->desc) + return; + + /* enable compression */ + if (!ch->desc->out_compress) + { + send_to_char("Trying compression.\n\r", ch); + write_to_buffer(ch->desc, will_compress2, 0); + write_to_buffer(ch->desc, will_compress, 0); + } + else /* disable compression */ + { + if (!compressEnd(ch->desc)) + { + send_to_char("Failed.\n\r", ch); + return; + } + send_to_char("Compression disabled.\n\r", ch); + } +} + + void game_loop_unix( int control ) { static struct timeval null_time; struct timeval last_time; @@ -975,10 +1001,13 @@ * Init descriptor data. */ dnew->next = descriptor_list; descriptor_list = dnew; + write_to_buffer(dnew, will_compress2, 0); + write_to_buffer(dnew, will_compress, 0); + /* * Send the greeting. */ { extern char * help_greeting; @@ -1061,10 +1090,12 @@ d->next = dclose->next; else bug( "Close_socket: dclose not found.", 0 ); } + compressEnd(dclose); + close( dclose->descriptor ); free_string( dclose->host ); /* RT socket leak fix */ free_mem( dclose->outbuf, dclose->outsize ); @@ -1143,10 +1174,13 @@ if ( d != NULL ) d->next = dclose->next; else bug( "Close_socket: dclose not found.", 0 ); } + + compressEnd(dclose); + close( dclose->descriptor ); free_string( dclose->host ); dclose->next = descriptor_free; descriptor_free = dclose; #if defined(MSDOS) || defined(macintosh) @@ -1234,11 +1268,11 @@ /* * Transfer one line from input buffer to input line. */ void read_from_buffer( DESCRIPTOR_DATA *d ) { - int i, j, k; + int i, j, k, telopt; /* * Hold horses if pending command already. */ if ( d->incomm[0] != '\0' ) @@ -1271,11 +1305,33 @@ d->inbuf[i] = '\n'; d->inbuf[i+1] = '\0'; break; } - if ( d->inbuf[i] == '\b' && k > 0 ) + if (d->inbuf[i] == (signed char) IAC) + telopt = 1; + else if (telopt == 1 && (d->inbuf[i] == (signed char) DO || d->inbuf[i] == (signed char) DONT)) + telopt = 2; + else if (telopt == 2) + { + telopt = 0; + if (d->inbuf[i] == (signed char) TELOPT_COMPRESS) + { + if (d->inbuf[i-1] == (signed char) DO) + compressStart(d, TELOPT_COMPRESS); + else if (d->inbuf[i-1] == (signed char) DONT) + compressEnd(d); + } + else if (d->inbuf[i] == (signed char) TELOPT_COMPRESS2) + { + if (d->inbuf[i-1] == (signed char) DO) + compressStart(d, TELOPT_COMPRESS2); + else if (d->inbuf[i-1] == (signed char) DONT) + compressEnd(d); + } + } + else if ( d->inbuf[i] == '\b' && k > 0 ) --k; else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) ) d->incomm[k++] = d->inbuf[i]; } @@ -1516,21 +1572,70 @@ * 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 ) { + DESCRIPTOR_DATA *d; int iStart; int nWrite; int nBlock; + int len; #if defined(macintosh) || defined(MSDOS) if ( desc == 0 ) desc = 1; #endif if ( length <= 0 ) length = strlen(txt); + + for (d = descriptor_list; d; d = d->next) + { + if (d->descriptor == desc) break; + } + if (!d) + { + bug("Write_to_descriptor: No descriptor", 0); + return FALSE; + } + + if (d->out_compress) + { + d->out_compress->next_in = (unsigned char *) txt; + d->out_compress->avail_in = length; + + while (d->out_compress->avail_in) + { + d->out_compress->avail_out = COMPRESS_BUF_SIZE - (d->out_compress->next_out - d->out_compress_buf); + + if (d->out_compress->avail_out) + { + int status = deflate(d->out_compress, Z_SYNC_FLUSH); + + if (status != Z_OK) return FALSE; + } + len = d->out_compress->next_out - d->out_compress_buf; + if (len > 0) + { + for (iStart = 0; iStart < len; iStart += nWrite) + { + nBlock = UMIN (len - iStart, 4096); + if ((nWrite = write(d->descriptor, d->out_compress_buf + iStart, nBlock)) < 0) + { + perror( "Write_to_descriptor: compressed" ); + return FALSE; + } + if (!nWrite) break; + } + if (!iStart) break; + if (iStart < len) + memmove(d->out_compress_buf, d->out_compress_buf+iStart, len - iStart); + d->out_compress->next_out = d->out_compress_buf + len - iStart; + } + } + return TRUE; + } for ( iStart = 0; iStart < length; iStart += nWrite ) { nBlock = UMIN( length - iStart, 4096 ); if ( ( nWrite = write( desc, txt + iStart, nBlock ) ) < 0 ) diff -bBdNrw -U5 old/mccp.c src/mccp.c --- old/mccp.c Wed Dec 31 19:00:00 1969 +++ src/mccp.c Tue Aug 21 15:02:15 2001 @@ -0,0 +1,185 @@ +/* + * 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" + +bool processCompressed(DESCRIPTOR_DATA *desc); + +char compress_start [] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, '\0' }; +char compress_start2 [] = { IAC, SB, TELOPT_COMPRESS2, IAC, SE, '\0' }; + +/* + * 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, unsigned char telopt) +{ + 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; + } + + if (telopt == TELOPT_COMPRESS) + write_to_descriptor(desc->descriptor, compress_start, 0); + else + write_to_descriptor(desc->descriptor, compress_start2, 0); + + /* now we're compressing */ + desc->out_compress = s; + desc->compressing = telopt; + 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; +} diff -bBdNrw -U5 old/merc.h src/merc.h --- old/merc.h Tue Aug 21 15:01:46 2001 +++ src/merc.h Tue Aug 21 15:08:25 2001 @@ -13,10 +13,11 @@ * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ +#include /* * Accommodate old non-Ansi compilers. */ @@ -186,10 +187,15 @@ #define PULSE_MOBILE ( 4 * PULSE_PER_SECOND) #define PULSE_TICK (30 * PULSE_PER_SECOND) #define PULSE_AREA (60 * PULSE_PER_SECOND) #define PULSE_WW ( 4 * PULSE_PER_SECOND) +#define TELOPT_COMPRESS 85 +#define TELOPT_COMPRESS2 86 +#define COMPRESS_BUF_SIZE 8192 +bool write_to_descriptor args (( int desc, char *txt, int length )); + /* * Rotains Clan Table Structure */ @@ -289,10 +295,13 @@ char inlast [MAX_INPUT_LENGTH]; int repeat; char * outbuf; int outsize; int outtop; + unsigned char compressing; + z_stream * out_compress; + unsigned char * out_compress_buf; }; /*