diff --git a/cstp.c b/cstp.c index bdcf3dd4..048920f4 100644 --- a/cstp.c +++ b/cstp.c @@ -575,18 +575,9 @@ int openconnect_make_cstp_connection(struct openconnect_info *vpninfo) if (ret) goto out; - if (vpninfo->cstp_compr == COMPR_LZS) { - if (!vpninfo->lzs_state) - vpninfo->lzs_state = alloc_lzs_state(); - if (!vpninfo->lzs_state) { - vpn_progress(vpninfo, PRG_ERR, _("Compression setup failed\n")); - ret = -ENOMEM; - goto out; - } - - /* This will definitely be smaller than zlib's */ + /* This will definitely be smaller than zlib's */ + if (vpninfo->cstp_compr == COMPR_LZS) deflate_bufsize = vpninfo->ip_info.mtu; - } /* If deflate compression is enabled (which is CSTP-only), it needs its * context to be allocated. */ @@ -1111,8 +1102,7 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout) vpninfo->pending_deflated_pkt = this; vpninfo->current_ssl_pkt = vpninfo->deflate_pkt; } else if (vpninfo->cstp_compr == COMPR_LZS) { - ret = lzs_compress(vpninfo->lzs_state, - vpninfo->deflate_pkt->data, this->len, + ret = lzs_compress(vpninfo->deflate_pkt->data, this->len, this->data, this->len); if (ret < 0) goto uncompr; /* It only ever returns -EFBIG */ diff --git a/dtls.c b/dtls.c index dd8693bc..8b58acc8 100644 --- a/dtls.c +++ b/dtls.c @@ -860,8 +860,7 @@ int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout) if (vpninfo->dtls_compr & COMPR_LZS && this->len > 0x40 && vpninfo->current_ssl_pkt != vpninfo->deflate_pkt) { - ret = lzs_compress(vpninfo->lzs_state, - vpninfo->deflate_pkt->data, this->len, + ret = lzs_compress(vpninfo->deflate_pkt->data, this->len, this->data, this->len); if (ret > 0) { send_pkt = vpninfo->deflate_pkt; diff --git a/library.c b/library.c index 96d8b793..f9f66e49 100644 --- a/library.c +++ b/library.c @@ -291,7 +291,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo) /* These check strm->state so they are safe to call multiple times */ inflateEnd(&vpninfo->inflate_strm); deflateEnd(&vpninfo->deflate_strm); - free(vpninfo->lzs_state); + free(vpninfo->deflate_pkt); free(vpninfo->tun_pkt); free(vpninfo->dtls_pkt); diff --git a/lzs.c b/lzs.c index 049aefc6..895d93b8 100644 --- a/lzs.c +++ b/lzs.c @@ -158,7 +158,16 @@ do { \ * Much of the compression algorithm used here is based very loosely on ideas * from isdn_lzscomp.c by Andre Beck: http://micky.ibh.de/~beck/stuff/lzs4i4l/ */ -struct lzs_state { +int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen) +{ + int inpos = 0; + uint32_t match_len; + uint32_t hash; + uint16_t hofs, longest_match_len, longest_match_ofs; + int outpos = 0; + uint32_t outbits = 0; + int nr_outbits = 0; + /* * Each pair of bytes from the input is hashed into a hash value of * size HASH_BITS (currently 12 bits). We could use 16 bits and stop @@ -186,71 +195,32 @@ struct lzs_state { * offset will yield the previous offset at which the same data hash * value was found. */ -#define MAX_HISTORY (1ULL<<11) /* Highest offset LZS can represent is 11 bits */ +#define MAX_HISTORY (1<<11) /* Highest offset LZS can represent is 11 bits */ uint16_t hash_chain[MAX_HISTORY]; -}; - -struct lzs_state *alloc_lzs_state(void) -{ - struct lzs_state *lzs = malloc(sizeof(*lzs)); - if (!lzs) - return NULL; - - memset(lzs->hash_table, 0xff, sizeof(lzs->hash_table)); - memset(lzs->hash_chain, 0xff, sizeof(lzs->hash_chain)); - - return lzs; -} - -int lzs_compress(struct lzs_state *lzs, unsigned char *dst, int dstlen, - const unsigned char *src, int srclen) -{ - int inpos = 0; - uint32_t match_len; - uint32_t hash; - uint32_t hofs, longest_match_len, longest_match_ofs; - int outpos = 0; - uint32_t outbits = 0; - int nr_outbits = 0; - /* Just in case anyone tries to use this in a more general-purpose * scenario... */ - if (srclen > 0x10000) + if (srclen > INVALID_OFS + 1) return -EFBIG; + /* There are ways we could probably avoid having to do this memset + * each time... */ + memset(hash_table, 0xff, sizeof(hash_table)); + memset(hash_chain, 0xff, sizeof(hash_chain)); + while (inpos < srclen - 1) { hash = HASH(src + inpos); - hofs = lzs->hash_table[hash]; + hofs = hash_table[hash]; longest_match_len = 0; - /* If there is a stale entry in the hash table from a previous - * packet, then clear it. This is what makes it OK to re-use the - * data structures without clearing them each time; the first time - * we see any given hash value in the current packet, we'll reset - * the chain. - * - * We don't have to worry about the contents of hash_chain because - * we should only ever be following links to entries in that which - * *have* been written this time around. */ - if (hofs >= inpos || hash != HASH(src + hofs)) - hofs = lzs->hash_table[hash] = INVALID_OFS; - - /* inpos can never exceed INVALID_OFS-1 so there's no need for an - * explicit check for hofs != INVALID_OFS. */ - while (hofs < inpos && hofs + MAX_HISTORY > inpos) { - match_len = find_match_len(src, hofs, inpos, - longest_match_len ? : 2, srclen - inpos); + while (hofs != INVALID_OFS && hofs + MAX_HISTORY > inpos) { + match_len = find_match_len(src, hofs, inpos, longest_match_len ? : 2, srclen - inpos); if (match_len > longest_match_len) { longest_match_len = match_len; longest_match_ofs = hofs; } - /* Sanity check to prevent looping — we should always be - * working *backwards* */ - if (lzs->hash_chain[hofs & (MAX_HISTORY - 1)] >= hofs) - break; - hofs = lzs->hash_chain[hofs & (MAX_HISTORY - 1)]; + hofs = hash_chain[hofs & (MAX_HISTORY - 1)]; } if (longest_match_len) { /* Output offset, as 7-bit or 11-bit as appropriate */ @@ -290,12 +260,8 @@ int lzs_compress(struct lzs_state *lzs, unsigned char *dst, int dstlen, while (longest_match_len--) { hash = HASH(src + inpos); - /* Don't link to stale hash chains. */ - if (hofs >= inpos || hash != HASH(src + hofs)) - lzs->hash_chain[inpos & (MAX_HISTORY - 1)] = INVALID_OFS; - else - lzs->hash_chain[inpos & (MAX_HISTORY - 1)] = lzs->hash_table[hash]; - lzs->hash_table[hash] = inpos++; + hash_chain[inpos & (MAX_HISTORY - 1)] = hash_table[hash]; + hash_table[hash] = inpos++; } } if (inpos < srclen) diff --git a/lzstest.c b/lzstest.c index e5e27350..41ae3387 100644 --- a/lzstest.c +++ b/lzstest.c @@ -18,10 +18,8 @@ #define __OPENCONNECT_INTERNAL_H__ -struct lzs_state; -struct lzs_state *alloc_lzs_state(void); int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen); -int lzs_compress(struct lzs_state *lzs, unsigned char *dst, int dstlen, const unsigned char *src, int srclen); +int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen); #include "lzs.c" @@ -40,7 +38,6 @@ int main(void) unsigned char pktbuf[MAX_PKT + 3]; unsigned char comprbuf[MAX_PKT * 9 / 8 + 2]; unsigned char uncomprbuf[MAX_PKT]; - struct lzs_state *lzs = alloc_lzs_state(); srand(0xdeadbeef); @@ -64,7 +61,7 @@ int main(void) *(int *)(pktbuf + j) = r; } - ret = lzs_compress(lzs, comprbuf, sizeof(comprbuf), pktbuf, pktlen); + ret = lzs_compress(comprbuf, sizeof(comprbuf), pktbuf, pktlen); if (ret < 0) { fprintf(stderr, "Compressing packet %d failed: %s\n", i, strerror(-ret)); exit(1); diff --git a/openconnect-internal.h b/openconnect-internal.h index 6bd64a54..1a3f31d2 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -194,8 +194,6 @@ struct proxy_auth_state { char *challenge; }; -struct lzs_state; - struct openconnect_info { #ifdef HAVE_ICONV iconv_t ic_legacy_to_utf8; @@ -371,8 +369,6 @@ struct openconnect_info { z_stream deflate_strm; uint32_t deflate_adler32; - struct lzs_state *lzs_state; - int disable_ipv6; int reconnect_timeout; int reconnect_interval; @@ -640,9 +636,7 @@ int decompress_and_queue_packet(struct openconnect_info *vpninfo, /* lzs.c */ int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen); -int lzs_compress(struct lzs_state *, unsigned char *dst, int dstlen, - const unsigned char *src, int srclen); -struct lzs_state *alloc_lzs_state(void); +int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen); /* ssl.c */ unsigned string_is_hostname(const char* str);