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:
parent
92ac3393ed
commit
efce757995
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=52729
@ -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>
|
||||
|
218
net/tinyfugue/files/mccp-patch
Normal file
218
net/tinyfugue/files/mccp-patch
Normal 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
426
net/tinyfugue/files/mccp.c
Normal 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
141
net/tinyfugue/files/mccp.h
Normal 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
|
Loading…
Reference in New Issue
Block a user