1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-11-23 00:43:28 +00:00

- add -DWITH_MCCP (mccp v1/v2 support)

- assume maintainership
This commit is contained in:
Max Khon 2002-01-07 20:26:38 +00:00
parent 92ac3393ed
commit efce757995
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=52729
4 changed files with 802 additions and 2 deletions

View File

@ -13,7 +13,7 @@ MASTER_SITES= ftp://tf.tcp.com/pub/tinyfugue/ \
ftp://ftp.ci.uminho.pt/pub/mirrors/tinyfugue/
DISTNAME= tf-40s1
MAINTAINER= ports@FreeBSD.org
MAINTAINER= fjoe@FreeBSD.org
.if defined(PARALLEL_PACKAGE_BUILD)
BROKEN= tries to cd to directory that do not exist yet
@ -26,4 +26,19 @@ MAKE_ENV= TFVER=${DISTNAME:S/^tf-//}
MAN1= tf.1
.include <bsd.port.mk>
.include <bsd.port.pre.mk>
.if defined(WITH_MCCP)
EXTRA_PATCHES= ${FILESDIR}/mccp-patch
PKGNAMESUFFIX= -mccp
post-extract:
@${CP} ${FILESDIR}/mccp.[ch] ${WRKSRC}/src
.else
pre-extract:
@${ECHO_MSG}
@${ECHO_MSG} "You can enable MCCP v1/v2 support by defining WITH_MCCP"
@${ECHO_MSG}
.endif
.include <bsd.port.post.mk>

View File

@ -0,0 +1,218 @@
--- src/rules.mak.orig Sun Mar 7 04:43:25 1999
+++ src/rules.mak Fri Jun 23 05:46:38 2000
@@ -50,6 +50,7 @@ main.$O: main.c config.h port.h dstring.
variable.h tty.h $(BUILDERS)
makehelp.$O: makehelp.c config.h port.h $(BUILDERS)
malloc.$O: malloc.c config.h port.h signals.h malloc.h $(BUILDERS)
+mccp.$O: mccp.c mccp.h
output.$O: output.c config.h port.h dstring.h $(TF_H) util.h tfio.h socket.h \
output.h macro.h search.h tty.h variable.h expr.h $(BUILDERS)
process.$O: process.c config.h port.h dstring.h $(TF_H) util.h tfio.h \
@@ -59,7 +60,7 @@ signals.$O: signals.c config.h port.h ds
process.h tty.h output.h signals.h variable.h $(BUILDERS)
socket.$O: socket.c config.h port.h dstring.h $(TF_H) util.h tfio.h tfselect.h \
history.h world.h socket.h output.h process.h macro.h keyboard.h \
- commands.h command.h signals.h search.h $(BUILDERS)
+ commands.h command.h signals.h search.h mccp.h $(BUILDERS)
tfio.$O: tfio.c config.h port.h dstring.h $(TF_H) util.h tfio.h tfselect.h \
output.h macro.h history.h search.h signals.h variable.h $(BUILDERS)
tty.$O: tty.c config.h port.h $(TF_H) dstring.h util.h tty.h output.h macro.h \
--- src/socket.c.orig Sun Mar 7 04:43:25 1999
+++ src/socket.c Sat Jul 1 06:22:52 2000
@@ -67,6 +67,10 @@ struct sockaddr_in {
#include "search.h"
#include "variable.h" /* set_var_by_*() */
+#ifdef MUDCOMPRESS
+# include "mccp.h"
+#endif
+
#ifdef _POSIX_VERSION
# include <sys/wait.h>
#endif
@@ -206,6 +210,9 @@ typedef struct Sock { /* an open connec
TIME_T time[2]; /* time of last receive/send */
char state; /* state of parser finite state automaton */
long pid; /* pid of name resolution process */
+#ifdef MUDCOMPRESS
+ mc_state *mccp; /* mud compression struct */
+#endif
} Sock;
@@ -806,6 +813,9 @@ int opensock(world, autologin, quietlogi
tsock = *(tsock ? &tsock->next : &hsock) = xsock;
xsock->activity = 0;
Stringinit(xsock->buffer);
+#ifdef MUDCOMPRESS
+ xsock->mccp = mudcompress_new();
+#endif
xsock->prompt = NULL;
init_queue(xsock->queue = (Queue *)XMALLOC(sizeof(Queue)));
xsock->next = NULL;
@@ -1297,6 +1307,9 @@ static void nukesock(sock)
#endif /* NONBLOCKING_GETHOST */
}
Stringfree(sock->buffer);
+#ifdef MUDCOMPRESS
+ mudcompress_delete(sock->mccp);
+#endif
if (sock->prompt) free_aline(sock->prompt);
while(sock->queue->head)
free_aline((Aline*)unlist(sock->queue->head, sock->queue));
@@ -1728,8 +1741,25 @@ static int handle_socket_input()
}
do { /* while (n > 0 && !interrupted() && (received += count) < SPAM) */
- do count = recv(xsock->fd, buffer, sizeof(buffer), 0);
- while (count < 0 && errno == EINTR);
+#ifdef MUDCOMPRESS
+ if (!mudcompress_pending(xsock->mccp))
+ {
+ do count = recv(xsock->fd, buffer, sizeof(buffer), 0);
+ while (count < 0 && errno == EINTR);
+
+ if (count > 0) {
+ mudcompress_receive(xsock->mccp, buffer, count);
+ if (mudcompress_error(xsock->mccp)) {
+ count = -1;
+ errno = EIO;
+ }
+ }
+ }
+#else
+ do count = recv(xsock->fd, buffer, sizeof(buffer), 0);
+ while (count < 0 && errno == EINTR);
+#endif
+
if (count <= 0) {
int err = errno;
#ifdef SUNOS_5_4
@@ -1761,6 +1791,25 @@ static int handle_socket_input()
return received;
}
+ received += count;
+
+#ifdef MUDCOMPRESS
+ {
+ const char *resp;
+
+ count = 0;
+ while (count < sizeof(buffer)
+ && mudcompress_pending(xsock->mccp)) {
+ count += mudcompress_get(xsock->mccp, buffer + count,
+ sizeof(buffer) - count);
+ }
+
+ resp = mudcompress_response(xsock->mccp);
+ if (resp)
+ transmit(resp,strlen(resp));
+ }
+#endif
+
for (place = buffer; place - buffer < count; place++) {
/* We always accept 8-bit data, even though RFCs 854 and 1123
@@ -1958,7 +2007,6 @@ static int handle_socket_input()
}
/* See if anything arrived while we were parsing */
-
FD_ZERO(&readfds);
FD_SET(xsock->fd, &readfds);
tv.tv_sec = tv.tv_usec = 0;
@@ -1976,7 +2024,13 @@ static int handle_socket_input()
if (errno != EINTR) die("handle_socket_input: select", errno);
}
- } while (n > 0 && !interrupted() && (received += count) < SPAM);
+#ifdef MUDCOMPRESS
+ if (mudcompress_pending(xsock->mccp)) {
+ n = 1;
+ }
+#endif
+
+ } while (n > 0 && !interrupted() && received < SPAM);
/* If lpflag is on and we got a partial line from the fg world,
* assume the line is a prompt.
--- src/tf.1.catman.orig Sun Mar 7 04:43:25 1999
+++ src/tf.1.catman Sat Jun 24 01:25:46 2000
@@ -152,6 +152,8 @@ TF(1)
Recall previously received text.
+ Support for the Mud Client Compression Protocol version 1 and 2.
+
CCOONNFFIIGGUURRAATTIIOONN FFIILLEESS
_T_F will attempt to read two files when starting. The
--- src/tf.1.nroffman.orig Sun Mar 7 04:43:25 1999
+++ src/tf.1.nroffman Sat Jun 24 01:25:04 2000
@@ -112,6 +112,8 @@ Separate LP and Diku style prompts from
Page output using a --More-- prompt.
.sp
Recall previously received text.
+.sp
+Support for Mud Client Compression Protocol versions 1 and 2.
.SH "CONFIGURATION FILES"
.PP
--- src/vars.mak.orig Sun Mar 7 04:43:25 1999
+++ src/vars.mak Fri Jun 23 06:07:44 2000
@@ -15,14 +15,14 @@
# Predefined variables:
# O - object file suffix (e.g., "o" or "obj")
-TFVER=40s1
+TFVER=40s1-mccp
SOURCE = command.c dstring.c expand.c help.c history.c keyboard.c \
macro.c main.c malloc.c output.c process.c search.c signals.c \
socket.c tfio.c tty.c util.c variable.c world.c
OBJS = command.$O dstring.$O expand.$O expr.$O help.$O history.$O keyboard.$O \
- macro.$O main.$O malloc.$O output.$O process.$O search.$O signals.$O \
+ macro.$O main.$O malloc.$O mccp.$O output.$O process.$O search.$O signals.$O \
socket.$O tfio.$O tty.$O util.$O variable.$O world.$O \
regexp.$O $(OTHER_OBJS)
--- unix/tfconfig.orig Sun Mar 7 04:43:28 1999
+++ unix/tfconfig Wed Jul 5 05:56:02 2000
@@ -482,6 +482,14 @@ else
echo "I can't find <pwd.h>. Filename '~user' expansion won't be supported."
fi
+### Find zlib.h
+if echo '#include <zlib.h>' >test.c; ${CPP} test.c >/dev/null 2>&1; then
+ echo "#define MUDCOMPRESS" >&4
+ echo "Found <zlib.h>."
+else
+ echo "I can't find <zlib.h>. The Mud Client Compression Protocol will not be supported."
+fi
+
### Figure out how to do varadic args.
if [ "$STD_C" = "1" ] || [ "$GNU_C" = "1" ]; then
if echo '#include <stdarg.h>' >test.c; ${CPP} test.c >/dev/null 2>&1; then
@@ -756,6 +764,12 @@ elif eval "${LIBTEST} -lsocket ${LIBS} >
else
echo "Warning: can't find connect() or a library that might have it."
echo "/* warning: tfconfig couldn't find connect() */" >&4
+fi
+
+### Test for zlib for mud compression
+if eval "${LIBTEST} -lz ${LIBS} >/dev/null 2>&1" && test -f ${AOUT}; then
+ echo "Will link with -lz."
+ LIBS="-lz $LIBS"
fi
### Test for SOCKS firewall proxy server.
--- unixmake.orig Sun Mar 7 04:43:24 1999
+++ unixmake Sat Jul 1 06:27:28 2000
@@ -20,4 +20,4 @@ export PATH
MAKE=${MAKE-make}
export MAKE
-${MAKE} -f unix/Makefile `egrep '^TFVER=' src/vars.mak` MAKE="${MAKE}" $*
+${MAKE} -j 1 -f unix/Makefile `egrep '^TFVER=' src/vars.mak` MAKE="${MAKE}" $*

426
net/tinyfugue/files/mccp.c Normal file
View File

@ -0,0 +1,426 @@
/*
* Client decompression module for the mud client compression protocol.
* See http://homepages.ihug.co.nz/~icecube/compress/ for more details.
*
* mccpDecompress.c - module code. Link this with your client code.
*
* Oliver Jowett <icecube$ihug.co.nz>. Demangle address as needed.
*
* This code is placed in the public domain.
*
*/
/* Modified: 20000530 */
/* See mccp.h for API information */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#ifdef MUDCOMPRESS
#include <zlib.h>
#include "mccp.h"
/* Telnet values we're interested in */
#define IAC 255
#define DONT 254
#define DO 253
#define WONT 252
#define WILL 251
#define SB 250
#define SE 240
#define TELOPT_COMPRESS 85
#define TELOPT_COMPRESS2 86
/* We say DO COMPRESS2 to WILL COMPRESS2, then DONT COMPRESS to WILL COMPRESS
* -or-
* We say DO COMPRESS to WILL COMPRESS if it arrives before any COMPRESS2.
*
* Later the server sends IAC SB COMPRESS IAC SE (v2) or IAC SB COMPRESS WILL
* SE (v1), and immediately following
* that, begins compressing
*
* Compression ends on a Z_STREAM_END, no other marker is used
*/
static char will_v1[] = { IAC, WILL, TELOPT_COMPRESS, 0 };
static char do_v1[] = { IAC, DO, TELOPT_COMPRESS, 0 };
static char dont_v1[] = { IAC, DONT, TELOPT_COMPRESS, 0 };
static char on_v1[] = { IAC, SB, TELOPT_COMPRESS, WILL, SE, 0 };
static char will_v2[] = { IAC, WILL, TELOPT_COMPRESS2, 0 };
static char do_v2[] = { IAC, DO, TELOPT_COMPRESS2, 0 };
static char on_v2[] = { IAC, SB, TELOPT_COMPRESS2, IAC, SE, 0 };
/* "Opaque" state object */
struct mc_state_s {
z_stream *stream; /* stream we're using */
unsigned char *inbuf; /* input buffer (data from mud) */
unsigned int insize; /* .. and how much is used */
unsigned int inalloc; /* .. and how much is allocated */
unsigned char *outbuf; /* output buffer (data to user) */
unsigned int outsize; /* .. and how much is used */
unsigned int outalloc; /* .. and how much is allocated */
int error;
int resp_v1; /* waiting to send IAC DO/DONT COMPRESS */
int resp_v2; /* waiting to send IAC DO COMPRESS2 */
int got_v2; /* responded to a IAC WILL COMPRESS2 already */
unsigned long comp;
unsigned long uncomp;
};
/* Initialise a new state object */
mc_state *mudcompress_new(void)
{
mc_state *state;
state = malloc(sizeof(*state));
state->stream = NULL; /* Not decompressing */
state->inalloc = 2048;
state->outalloc = 2048;
state->inbuf = malloc(state->inalloc);
state->outbuf = malloc(state->outalloc);
state->insize = 0;
state->outsize = 0;
state->error = 0;
state->comp = 0;
state->uncomp = 0;
state->resp_v1 = 0;
state->resp_v2 = 0;
state->got_v2 = 0;
return state;
}
/* Clean up a state object */
void mudcompress_delete(mc_state *state)
{
if (state->stream) {
inflateEnd(state->stream);
free(state->stream);
}
free(state->inbuf);
free(state->outbuf);
free(state);
}
/* zlib helpers */
static void *zlib_alloc(void *opaque, unsigned int items, unsigned int size)
{
return calloc(items, size);
}
static void zlib_free(void *opaque, void *address)
{
free(address);
}
static void grow_inbuf(mc_state *state, int needed)
{
int old = state->inalloc;
while (state->inalloc < state->insize + needed)
state->inalloc *= 2;
if (old != state->inalloc)
state->inbuf = realloc(state->inbuf, state->inalloc);
}
static void grow_outbuf(mc_state *state, int needed)
{
int old = state->outalloc;
while (state->outalloc < state->outsize + needed)
state->outalloc *= 2;
if (old != state->outalloc)
state->outbuf = realloc(state->outbuf, state->outalloc);
}
static void decompress_inbuf(mc_state *state)
{
int status;
/* We are now decompressing from inbuf to outbuf */
if (!state->insize)
return; /* nothing to decompress? */
state->stream->next_in = state->inbuf;
state->stream->next_out = state->outbuf + state->outsize;
state->stream->avail_in = state->insize;
state->stream->avail_out = state->outalloc - state->outsize;
status = inflate(state->stream, Z_PARTIAL_FLUSH);
if (status == Z_OK || status == Z_STREAM_END) {
/* Successful decompression */
/* Remove used data from inbuf */
state->comp += state->insize - state->stream->avail_in;
state->uncomp += state->stream->next_out - state->outbuf;
memmove(state->inbuf, state->stream->next_in, state->stream->avail_in);
state->insize = state->stream->avail_in;
/* Update outbuf pointers */
state->outsize = state->stream->next_out - state->outbuf;
/* Done */
if (status == Z_STREAM_END) {
/* Turn off compression too */
grow_outbuf(state, state->insize);
memcpy(state->outbuf + state->outsize, state->inbuf, state->insize);
state->outsize += state->insize;
state->insize = 0;
inflateEnd(state->stream);
free(state->stream);
state->stream = NULL;
}
return;
}
if (status == Z_BUF_ERROR) {
/* Full buffers? Maybe we need more output space.. */
if (state->outsize * 2 > state->outalloc) {
grow_outbuf(state, state->outalloc);
decompress_inbuf(state);
}
return;
}
/* Error */
state->error = 1;
}
/* We received some data */
void mudcompress_receive(mc_state *state, const char *data, unsigned len)
{
int i;
if (state->error)
return;
if (!state->stream) {
int residual = -1;
int clen;
/* Just copy to outbuf. Also copy any residual inbuf */
grow_outbuf(state, len + state->insize);
memcpy(state->outbuf + state->outsize, data, len);
state->outsize += len;
memcpy(state->outbuf + state->outsize, state->inbuf, state->insize);
state->outsize += state->insize;
state->insize = 0;
/* Check for Magic Marker. ugh this is messy */
for (i=0; i < state->outsize; i++) {
if (state->outbuf[i] == IAC) {
if (i + 1 < state->outsize && state->outbuf[i+1] == IAC) {
/* IAC IAC - ignore */
i++;
continue;
}
clen = (i + strlen(will_v1) < state->outsize) ? strlen(will_v1) : state->outsize - i;
if (!memcmp(&state->outbuf[i], will_v1, clen)) {
if (clen != strlen(will_v1)) {
/* Partial match. Save it. */
residual = i;
break;
}
/* If we got WILL COMPRESS2 then refuse COMPRESS, otherwise
* accept it
*/
if (state->got_v2)
state->resp_v1 = -1;
else
state->resp_v1 = 1;
memmove(&state->outbuf[i],
&state->outbuf[i + strlen(will_v1)],
state->outsize - strlen(will_v1));
state->outsize -= strlen(will_v1);
i--;
continue;
}
if (!memcmp(&state->outbuf[i], will_v2, clen)) {
if (clen != strlen(will_v2)) {
/* Partial match. Save it. */
residual = i;
break;
}
state->resp_v2 = 1;
state->got_v2 = 1;
memmove(&state->outbuf[i],
&state->outbuf[i + strlen(will_v2)],
state->outsize - strlen(will_v2));
state->outsize -= strlen(will_v2);
i--;
continue;
}
clen = (i + strlen(on_v1) < state->outsize) ? strlen(on_v1) : state->outsize - i;
if ((!memcmp(&state->outbuf[i], on_v1, clen) && !state->got_v2) ||
(!memcmp(&state->outbuf[i], on_v2, clen) && state->got_v2)) {
if (clen != strlen(on_v1)) {
/* Partial match. Save it. */
residual = i;
break;
}
/* Switch to compression */
/* copy any compressible bits to our inbuf */
grow_inbuf(state, state->outsize - i - strlen(on_v1));
memcpy(state->inbuf,
state->outbuf + i + strlen(on_v1),
state->outsize - i - strlen(on_v1));
state->insize = state->outsize - i - strlen(on_v1);
/* clean up our output buffer */
state->outsize = i;
/* init stream */
state->stream = malloc(sizeof(z_stream));
state->stream->zalloc = zlib_alloc;
state->stream->zfree = zlib_free;
state->stream->opaque = NULL;
if (inflateInit(state->stream) != Z_OK) {
state->error = 1;
free(state->stream);
state->stream = NULL;
return;
}
/* Continue with decompression */
break;
}
}
}
if (!state->stream) { /* didn't start decompressing? */
/* We might have some residual, copy to inbuf for later checking */
if (residual != -1) {
grow_inbuf(state, state->outsize - residual);
memcpy(state->inbuf + state->insize, state->outbuf + residual, state->outsize - residual);
state->outsize = residual;
}
return;
}
} else {
/* New data to decompress. Copy to inbuf */
grow_inbuf(state, len);
memcpy(state->inbuf + state->insize, data, len);
state->insize += len;
}
decompress_inbuf(state);
}
/* How much data is available? */
int mudcompress_pending(mc_state *state)
{
return state->error ? 0 : state->outsize;
}
/* Was there an error? */
int mudcompress_error(mc_state *state)
{
return state->error;
}
/* Get some data */
int mudcompress_get(mc_state *state, char *buf, int size)
{
int copied;
if (state->error || !state->outsize)
return 0;
if (size > state->outsize)
copied = state->outsize;
else
copied = size;
memcpy(buf, state->outbuf, copied);
state->outsize -= copied;
if (state->outsize)
memmove(state->outbuf, state->outbuf + copied, state->outsize);
/* Do some more decompression */
decompress_inbuf(state);
return copied;
}
void mudcompress_stats(mc_state *state, unsigned long *comp, unsigned long *uncomp)
{
*comp = state->comp;
*uncomp = state->uncomp;
}
const char *mudcompress_response(mc_state *state)
{
if (state->resp_v1 == 1) {
state->resp_v1 = 0;
return do_v1;
}
if (state->resp_v1 == -1) {
state->resp_v1 = 0;
return dont_v1;
}
if (state->resp_v2) {
state->resp_v2 = 0;
return do_v2;
}
return NULL;
}
int mudcompress_compressing(mc_state *state)
{
return (state->stream != NULL);
}
int mudcompress_v2(mc_state *state)
{
return (state->stream != NULL && state->got_v2);
}
#endif /* MUDCOMPRESS */

141
net/tinyfugue/files/mccp.h Normal file
View File

@ -0,0 +1,141 @@
/*
* Client decompression module for the mud client compression protocol.
* See http://homepages.ihug.co.nz/~icecube/compress/ for more details.
*
* mccpDecompress.h - header definitions. #include this in your client code.
*
* Oliver Jowett <icecube$ihug.co.nz>. Demangle address as needed.
*
* This code is placed in the public domain.
*
*/
/* Modified: 981203 */
/*
*
* mc_state is an opaque type representing the current compression state of
* a connection. You should include a (mc_state *) in the information you
* store for a server connection.
*
* Initialization / cleanup:
*
* When a connection is initiated, call mudcompress_new, and store the
* resulting pointer in your server connection information. This pointer is
* used as a handle for all other functions. This does NOT begin compression
* - it just initialises various internal structures.
*
* When a connection is terminated, call mudcompress_delete with the handle
* to delete all memory allocated by the decompressor for the connection.
*
* Reading / writing:
*
* Reading from the server connection must go through the decompressor at
* all times. The decompressor handles both negotiation and decompression
* transparently - it receives input directly from the server, then provides
* the main client code with decompressed data, hiding all protocol details.
*
* When data is received from the mud server, call mudcompress_receive,
* passing it the handle for the connection, a pointer to the data read,
* and the length of data read. It is VITAL that ALL data read is passed
* to the decompressor - including data with embedded NULs!
*
* After mudcompress_receive has been called, call mudcompress_pending() to
* see if any decompressed data is available. It returns the number of
* bytes pending.
*
* If there is pending data waiting, call mudcompress_get to retrieve it.
* This fills up to "size" bytes in the provided buffer "buf", and returns
* the number of bytes copied. Your client can now process this data as if
* it had been directly read from the server.
*
* Be sure to check mudcompress_pending again after calling mudcompress_get!
* Removing some data from the decompress buffer may have allowed the
* decompressor to decompress some more data - in which case, you want to
* process it immediately, rather than waiting for another read from the
* mud server.
*
* Regularly call mudcompress_response. If non-NULL, you need to write the
* returned string to the mud server. This is needed when the decompressor
* is negotiating compression with the server. When called,
* mudcompress_response clears any pending string, so be sure to save its
* return value!
*
* Status information:
*
* mudcompress_error returns non-0 if there has been a (fatal) decompression
* error. In this case, all you can do is tell the user that something went
* wrong and close the connection.
*
* mudcompress_stats fills in the two (unsigned long *) values passed, with
* the number of compressed bytes read, and the number of bytes that they
* decompressed to.
*
* mudcompress_compressing returns non-0 if the connection is currently
* using compression.
*
*/
#ifndef MUDCOMPRESS_H
#define MUDCOMPRESS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Opaque handle for a decompressor. Details defined in Compress.c - you
* should never need to see them externally.
*/
struct mc_state_s;
typedef struct mc_state_s mc_state;
/* Create a new decompressor. Return a handle to it.
*/
mc_state *mudcompress_new(void);
/* Deallocate a decompressor and associated data. 'state' is invalid
* afterthis call.
*/
void mudcompress_delete(mc_state *state);
/* Perform decompression and negotiation on some received data.
* 'data' is a pointer to the received data, 'len' is its length.
*/
void mudcompress_receive(mc_state *state, const char *data, unsigned len);
/* Return the number of pending decompressed bytes that can currently
* be read by mudcompress_get
*/
int mudcompress_pending(mc_state *state);
/* Return true (non-0) if this decompressor encountered a fatal error.
*/
int mudcompress_error(mc_state *state);
/* Read decompressed data from the decompressor into 'buf', up to a
* maximum of 'size' bytes. Returns the number of bytes actually copied.
*/
int mudcompress_get(mc_state *state, char *buf, int size);
/* Set *comp to the number of compressed bytes read, and *uncomp to the
* number of bytes they expanded to, for this decompressor.
*/
void mudcompress_stats(mc_state *state, unsigned long *comp, unsigned long *uncomp);
/* Check for a negotiation response. If this returns NULL, no output is
* needed. If it returns non-NULL, it points to a NUL-terminated string
* that should be sent to the mud server. Calling this function clears
* the pending string (so be sure to save the result).
*/
const char *mudcompress_response(mc_state *state);
/* Return true (non-0) if this decompressor has successfully negotiated
* compression and is currently performing decompression.
*/
int mudcompress_compressing(mc_state *state);
#ifdef __cplusplus
}
#endif
#endif