/*~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
~ Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, ~
~ Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. ~
~ ~
~ Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael ~
~ Chastain, Michael Quan, and Mitchell Tse. ~
~ ~
~ Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley ~
~ ACK!MUD is modified Merc2.0/2.1/2.2 code (c)Stephen Zepp 1998 Ver: 4.3 ~
~ ~
~ In order to use any part of this PA Diku Mud, you must comply with ~
~ both the original Diku license in 'license.doc' as well the Merc ~
~ license in 'license.txt', and the Ack!Mud license in 'ack_license.txt'.~
~ In particular, you may not remove any of these copyright notices. ~
~ ~
~ _______ _____ ~
~ / __ /\ / ___ \ 222222 PA_MUD by Amnon Kruvi ~
~ /______/ / / /___\ \ 2 PA_MUD is modified ~
~ / _______/ / _______ \ 2 Ack!Mud, v4.3 ~
~ /_/ /_/ \_\ 2 ~
~ 2 ~
~ 2222222 ~
~ ~
~ ~
~ Years of work have been invested to create DIKU, Merc, Ack and PA. ~
~ Please show your respect by following the licenses, and issuing ~
~ credits where due. ~
~ ~
~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-*/
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <arpa/telnet.h>
#include "ack.h"
#include "globals.h"
char compress_start [] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, '\0' };
char compress2_start [] = { IAC, SB, TELOPT_COMPRESS2, WILL, SE, '\0' };
char compress_on_str [] = { IAC, WILL, TELOPT_COMPRESS, '\0' };
char compress2_on_str [] = { IAC, WILL, TELOPT_COMPRESS2, '\0' };
bool processCompressed(DESCRIPTOR_DATA *desc);
bool write_to_descriptor args( ( DESCRIPTOR_DATA *d, char *txt, int length ) );
void *zlib_alloc(void *opaque, unsigned int items, unsigned int size)
{
return calloc(items, size);
}
void zlib_free(void *opaque, void *address)
{
free(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;
}
bool write_compressed( DESCRIPTOR_DATA * d, char *txt, int length )
{
int iStart = 0;
int nWrite = 0;
int nBlock;
int len;
if (length <= 0)
length = strlen(txt);
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(d->descriptor, txt + iStart, nBlock)) < 0)
{
perror( "Write_to_descriptor" );
return FALSE;
}
}
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);
s = (z_stream *)malloc(sizeof(*s));
d->out_compress_buf = (unsigned char *)malloc(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)
{
free(d->out_compress_buf);
free(s);
return FALSE;
}
if (telopt == TELOPT_COMPRESS)
write_to_descriptor(d, enable_compress, 0);
else if (telopt == TELOPT_COMPRESS2)
write_to_descriptor(d, enable_compress2, 0);
// else
// bug("compressStart: bad TELOPT passed");
d->compressing = telopt;
d->out_compress = s;
/* if ( d->character )
{
if ( telopt == 85 && !IS_SET(d->character->config,CONFIG_COMPRESS))
SET_BIT(d->character->config,CONFIG_COMPRESS);
if ( telopt == 86 && !IS_SET(d->character->config,CONFIG_COMPRESS2))
SET_BIT(d->character->config,CONFIG_COMPRESS2);
}*/
return TRUE;
}
bool compressEnd(DESCRIPTOR_DATA *d,unsigned char type)
{
unsigned char dummy[1];
unsigned char telopt;
if (!d->out_compress)
return TRUE;
if (d->compressing != type)
return FALSE;
// bug("Stopping compression for descriptor %d", d->descriptor);
d->out_compress->avail_in = 0;
d->out_compress->next_in = dummy;
telopt = d->compressing;
if (deflate(d->out_compress, Z_FINISH) != Z_STREAM_END)
return FALSE;
if ( !d )
return FALSE;
if (!process_compressed(d))
return FALSE;
deflateEnd(d->out_compress);
free(d->out_compress_buf);
free(d->out_compress);
d->compressing = 0;
d->out_compress_buf = NULL;
d->out_compress = NULL;
/* if ( d->character )
{
if ( telopt == 85 && IS_SET(d->character->config,CONFIG_COMPRESS))
REMOVE_BIT(d->character->config,CONFIG_COMPRESS);
if ( telopt == 86 && IS_SET(d->character->config,CONFIG_COMPRESS2))
REMOVE_BIT(d->character->config,CONFIG_COMPRESS2);
}*/
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) {
if ( str_cmp(argument,"2") )
write_to_buffer( ch->desc, compress_on_str, 0 );
if ( str_cmp(argument,"1") )
write_to_buffer( ch->desc, compress2_on_str, 0 );
send_to_char("Ok, compression enabled.\n", ch);
} else {
if (!compressEnd(ch->desc,ch->desc->compressing)) {
send_to_char("Failed.\n", ch);
return;
}
send_to_char("Ok, compression disabled.\n", ch);
}
return;
}