--- ./src/Makefile Thu May 27 22:18:59 1999 +++ ./src-mccp/Makefile Sat Jul 14 10:52:15 2001 @@ -24,9 +24,10 @@ #Uncomment the line below if you want a performance increase though beware #your core files may not be as much of a benefit if you do. #OPT_FLAG = -finline-functions -funroll-loops -fdefer-pop -fstrength-reduce +OPT_FLAG = -DMCCP C_FLAGS = $(OPT_FLAG) -O -g3 -Wall -Wuninitialized $(PROF) $(NOCRYPT) $(DBUGFLG) -DSMAUG $(SOLARIS_FLAG) $(TIME) $(REG) -L_FLAGS = $(OPT_FLAG) $(PROF) $(SOLARIS_LINK) $(NEED_CRYPT) +L_FLAGS = $(OPT_FLAG) $(PROF) $(SOLARIS_LINK) $(NEED_CRYPT) -lz #Uncomment the next three comments below if you want to use IMC #USE_IMC = -DUSE_IMC --- ./src/comm.c Thu May 27 22:19:00 1999 +++ ./src-mccp/comm.c Sat Jul 14 10:57:47 2001 @@ -73,6 +73,17 @@ const char echo_on_str [] = { IAC, WONT, TELOPT_ECHO, '\0' }; const char go_ahead_str [] = { IAC, GA, '\0' }; +#ifdef MCCP +#define TELOPT_COMPRESS 85 +#define TELOPT_COMPRESS2 86 +const char eor_on_str [] = { IAC, WILL, TELOPT_EOR, '\0' }; +const char compress_on_str [] = { IAC, WILL, TELOPT_COMPRESS, '\0' }; +const char compress2_on_str [] = { IAC, WILL, TELOPT_COMPRESS2, '\0' }; + +bool compressStart args( ( DESCRIPTOR_DATA *d, unsigned char telopt ) ); +bool compressEnd args( ( DESCRIPTOR_DATA *d ) ); +#endif + void auth_maxdesc args( ( int *md, fd_set *ins, fd_set *outs, fd_set *excs ) ); void auth_check args( ( fd_set *ins, fd_set *outs, fd_set *excs ) ); @@ -892,6 +904,12 @@ LINK( dnew, first_descriptor, last_descriptor, next, prev ); +#ifdef MCCP + write_to_buffer(dnew, eor_on_str, 0); + write_to_buffer(dnew, compress2_on_str, 0); + write_to_buffer(dnew, compress_on_str, 0); +#endif + /* * Send the greeting. */ @@ -934,6 +952,11 @@ STRFREE( d->user ); /* identd */ if ( d->pagebuf ) DISPOSE( d->pagebuf ); + +#ifdef MCCP + compressEnd(d); +#endif + DISPOSE( d ); /* --num_descriptors; This is called from more than close_socket -- Alty */ return; @@ -1058,6 +1081,10 @@ UNLINK( dclose, first_descriptor, last_descriptor, next, prev ); } +#ifdef MCCP + compressEnd(dclose); +#endif + if ( dclose->descriptor == maxdesc ) --maxdesc; @@ -1129,6 +1156,9 @@ void read_from_buffer( DESCRIPTOR_DATA *d ) { int i, j, k; +#ifdef MCCP + int iac = 0; +#endif /* * Hold horses if pending command already. @@ -1168,6 +1198,32 @@ break; } +#ifdef MCCP + if ( d->inbuf[i] == (signed char)IAC ) + iac=1; + else if ( iac==1 && (d->inbuf[i] == (signed char)DO || d->inbuf[i] == (signed char)DONT) ) + iac=2; + else if ( iac==2 ) + { + iac = 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 +#endif + if ( d->inbuf[i] == '\b' && k > 0 ) --k; else if ( isascii(d->inbuf[i]) && isprint(d->inbuf[i]) ) @@ -1393,6 +1449,85 @@ } +#ifdef MCCP +#define COMPRESS_BUF_SIZE 1024 + +bool write_to_descriptor( int desc, char *txt, int length ) +{ + DESCRIPTOR_DATA *d; + int iStart = 0; + int nWrite = 0; + int nBlock; + int len; + + if (length <= 0) + length = strlen(txt); + + for (d = first_descriptor; d; d = d->next) + if (d->descriptor == desc) + break; + + if (d->descriptor != desc) + d = NULL; + + if (d && 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) + { + perror( "Write_to_descriptor" ); + return FALSE; + } + } + + return TRUE; +} +#else /* * Lowest level output function. * Write a block of text to the file descriptor. @@ -1417,7 +1552,7 @@ return TRUE; } - +#endif void show_title( DESCRIPTOR_DATA *d ) @@ -3635,3 +3770,176 @@ } #endif + +#ifdef MCCP +/* + * Ported to SMAUG by Garil of DOTDII Mud + * aka Jesse DeFer http://www.dotd.com + * + * revision 1: MCCP v1 support + * revision 2: MCCP v2 support + * revision 3: Correct MMCP v2 support + * revision 4: clean up of write_to_descriptor() suggested by Noplex@CB + * + * See the web site below for more info. + */ + +/* + * 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. + */ + +void *zlib_alloc(void *opaque, unsigned int items, unsigned int size) +{ + return calloc(items, size); +} + +void zlib_free(void *opaque, void *address) +{ + DISPOSE(address); +} + +bool process_compressed(DESCRIPTOR_DATA *d) +{ + int iStart = 0, nBlock, nWrite, len; + + if (!d->out_compress) + return TRUE; + + // Try to write out some data.. + len = d->out_compress->next_out - d->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(d->descriptor, d->out_compress_buf + iStart, nBlock)) < 0) + { + if (errno == EAGAIN || + errno == ENOSR) + break; + + return FALSE; + } + + if (!nWrite) + break; + } + + if (iStart) + { + // We wrote "iStart" bytes + 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; +} + +char enable_compress[] = +{ + IAC, SB, TELOPT_COMPRESS, WILL, SE, 0 +}; +char enable_compress2[] = +{ + IAC, SB, TELOPT_COMPRESS2, IAC, SE, 0 +}; + +bool compressStart(DESCRIPTOR_DATA *d, unsigned char telopt) +{ + z_stream *s; + + if (d->out_compress) + return TRUE; + + bug("Starting compression for descriptor %d", d->descriptor); + + CREATE(s, z_stream, 1); + CREATE(d->out_compress_buf, unsigned char, COMPRESS_BUF_SIZE); + + s->next_in = NULL; + s->avail_in = 0; + + s->next_out = d->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) + { + DISPOSE(d->out_compress_buf); + DISPOSE(s); + return FALSE; + } + + if (telopt == TELOPT_COMPRESS) + write_to_descriptor(d->descriptor, enable_compress, 0); + else if (telopt == TELOPT_COMPRESS2) + write_to_descriptor(d->descriptor, enable_compress2, 0); + else + bug("compressStart: bad TELOPT passed"); + + d->compressing = telopt; + d->out_compress = s; + + return TRUE; +} + +bool compressEnd(DESCRIPTOR_DATA *d) +{ + unsigned char dummy[1]; + + if (!d->out_compress) + return TRUE; + + bug("Stopping compression for descriptor %d", d->descriptor); + + d->out_compress->avail_in = 0; + d->out_compress->next_in = dummy; + + if (deflate(d->out_compress, Z_FINISH) != Z_STREAM_END) + return FALSE; + + if (!process_compressed(d)) /* try to send any residual data */ + return FALSE; + + deflateEnd(d->out_compress); + DISPOSE(d->out_compress_buf); + DISPOSE(d->out_compress); + d->compressing = 0; + + return TRUE; +} + +void do_compress( CHAR_DATA *ch, char *argument ) +{ + if (!ch->desc) { + send_to_char("What descriptor?!\n", ch); + return; + } + + if (!ch->desc->out_compress) { + send_to_char("Initiating compression.\n\r", ch); + write_to_buffer( ch->desc, compress2_on_str, 0 ); + write_to_buffer( ch->desc, compress_on_str, 0 ); + } else { + send_to_char("Terminating compression.\n\r", ch); + compressEnd(ch->desc); + } + +} +#endif + --- ./src/mud.h Thu May 27 22:19:00 1999 +++ ./src-mccp/mud.h Wed Dec 13 20:59:12 2000 @@ -20,6 +20,9 @@ #include #include #include +#ifdef MCCP +#include +#endif /* force the who command to require an argument (should use cset) */ #define REQWHOARG @@ -738,6 +741,11 @@ char * user; int newstate; unsigned char prevcolor; +#ifdef MCCP + unsigned char compressing; + z_stream * out_compress; + unsigned char * out_compress_buf; +#endif }; @@ -3757,6 +3765,9 @@ DECLARE_DO_FUN( do_commands ); DECLARE_DO_FUN( do_comment ); DECLARE_DO_FUN( do_compare ); +#ifdef MCCP +DECLARE_DO_FUN( do_compress ); +#endif DECLARE_DO_FUN( do_config ); DECLARE_DO_FUN( do_consider ); DECLARE_DO_FUN( do_cook ); --- ./src/tables.c Thu May 27 22:19:01 1999 +++ ./src-mccp/tables.c Wed Dec 13 20:58:37 2000 @@ -232,6 +232,9 @@ if ( !str_cmp( name, "do_commands" )) return do_commands; if ( !str_cmp( name, "do_comment" )) return do_comment; if ( !str_cmp( name, "do_compare" )) return do_compare; +#ifdef MCCP + if ( !str_cmp( name, "do_compress" )) return do_compress; +#endif if ( !str_cmp( name, "do_config" )) return do_config; if ( !str_cmp( name, "do_consider" )) return do_consider; if ( !str_cmp( name, "do_cook" )) return do_cook; @@ -906,6 +909,9 @@ if ( skill == do_commands ) return "do_commands"; if ( skill == do_comment ) return "do_comment"; if ( skill == do_compare ) return "do_compare"; +#ifdef MCCP + if ( skill == do_compress ) return "do_compress"; +#endif if ( skill == do_config ) return "do_config"; if ( skill == do_consider ) return "do_consider"; if ( skill == do_cook ) return "do_cook";