376 lines · 10.5 KB · C
RawDownload
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> * Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se> * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * *   Redistributions of source code must retain the above *   copyright notice, this list of conditions and the *   following disclaimer. * *   Redistributions in binary form must reproduce the above *   copyright notice, this list of conditions and the following *   disclaimer in the documentation and/or other materials *   provided with the distribution. * *   Neither the name of the copyright holder nor the names *   of any other contributors may be used to endorse or *   promote products derived from this software without *   specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "libssh2_priv.h"#ifdef LIBSSH2_HAVE_ZLIB# include <zlib.h>#endif #include "comp.h" /* ******** * none * ******** */ /* * comp_method_none_comp * * Minimalist compression: Absolutely none */static intcomp_method_none_comp(LIBSSH2_SESSION *session,                      unsigned char *dest,                      size_t *dest_len,                      const unsigned char *src,                      size_t src_len,                      void **abstract){    (void) session;    (void) abstract;    (void) dest;    (void) dest_len;    (void) src;    (void) src_len;     return 0;} /* * comp_method_none_decomp * * Minimalist decompression: Absolutely none */static intcomp_method_none_decomp(LIBSSH2_SESSION * session,                        unsigned char **dest,                        size_t *dest_len,                        size_t payload_limit,                        const unsigned char *src,                        size_t src_len, void **abstract){    (void) session;    (void) payload_limit;    (void) abstract;    *dest = (unsigned char *) src;    *dest_len = src_len;    return 0;}   static const LIBSSH2_COMP_METHOD comp_method_none = {    "none",    0, /* not really compressing */    0, /* isn't used in userauth, go figure */    NULL,    comp_method_none_comp,    comp_method_none_decomp,    NULL}; #ifdef LIBSSH2_HAVE_ZLIB/* ******** * zlib * ******** */ /* Memory management wrappers * Yes, I realize we're doing a callback to a callback, * Deal... */ static voidpfcomp_method_zlib_alloc(voidpf opaque, uInt items, uInt size){    LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;     return (voidpf) LIBSSH2_ALLOC(session, items * size);} static voidcomp_method_zlib_free(voidpf opaque, voidpf address){    LIBSSH2_SESSION *session = (LIBSSH2_SESSION *) opaque;     LIBSSH2_FREE(session, address);}   /* libssh2_comp_method_zlib_init * All your bandwidth are belong to us (so save some) */static intcomp_method_zlib_init(LIBSSH2_SESSION * session, int compr,                      void **abstract){    z_stream *strm;    int status;     strm = LIBSSH2_ALLOC(session, sizeof(z_stream));    if (!strm) {        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,                              "Unable to allocate memory for "                              "zlib compression/decompression");    }    memset(strm, 0, sizeof(z_stream));     strm->opaque = (voidpf) session;    strm->zalloc = (alloc_func) comp_method_zlib_alloc;    strm->zfree = (free_func) comp_method_zlib_free;    if (compr) {        /* deflate */        status = deflateInit(strm, Z_DEFAULT_COMPRESSION);    } else {        /* inflate */        status = inflateInit(strm);    }     if (status != Z_OK) {        LIBSSH2_FREE(session, strm);        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,                       "unhandled zlib error %d", status);        return LIBSSH2_ERROR_COMPRESS;    }    *abstract = strm;     return LIBSSH2_ERROR_NONE;} /* * libssh2_comp_method_zlib_comp * * Compresses source to destination. Without allocation. */static intcomp_method_zlib_comp(LIBSSH2_SESSION *session,                      unsigned char *dest,                       /* dest_len is a pointer to allow this function to                         update it with the final actual size used */                      size_t *dest_len,                      const unsigned char *src,                      size_t src_len,                      void **abstract){    z_stream *strm = *abstract;    int out_maxlen = *dest_len;    int status;     strm->next_in = (unsigned char *) src;    strm->avail_in = src_len;    strm->next_out = dest;    strm->avail_out = out_maxlen;     status = deflate(strm, Z_PARTIAL_FLUSH);     if (status != Z_OK) {        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,                       "unhandled zlib compression error %d", status);        return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,                              "compression failure");    }     *dest_len = out_maxlen - strm->avail_out;    return 0;} /* * libssh2_comp_method_zlib_decomp * * Decompresses source to destination. Allocates the output memory. */static intcomp_method_zlib_decomp(LIBSSH2_SESSION * session,                        unsigned char **dest,                        size_t *dest_len,                        size_t payload_limit,                        const unsigned char *src,                        size_t src_len, void **abstract){    z_stream *strm = *abstract;    /* A short-term alloc of a full data chunk is better than a series of       reallocs */    char *out;    int out_maxlen = 8 * src_len;    int limiter = 0;     /* If strm is null, then we have not yet been initialized. */    if (strm == NULL)        return _libssh2_error(session, LIBSSH2_ERROR_COMPRESS,                              "decompression unitilized");;     /* In practice they never come smaller than this */    if (out_maxlen < 25)        out_maxlen = 25;     if (out_maxlen > (int) payload_limit)        out_maxlen = payload_limit;     strm->next_in = (unsigned char *) src;    strm->avail_in = src_len;    strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);    out = (char *) strm->next_out;    strm->avail_out = out_maxlen;    if (!strm->next_out)        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,                              "Unable to allocate decompression buffer");     /* Loop until it's all inflated or hit error */    for (;;) {        int status, grow_size;        size_t out_ofs;        char *newout;         status = inflate(strm, Z_PARTIAL_FLUSH);         if (status == Z_OK) {            if (! strm->avail_in) {                /* status is OK and input all used so we're done */                break;            }        } else if (status == Z_BUF_ERROR) {            /* This is OK, just drop through to grow the buffer */        } else {            /* error state */            LIBSSH2_FREE(session, out);            _libssh2_debug(session, LIBSSH2_TRACE_TRANS,                           "unhandled zlib error %d", status);            return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,                                  "decompression failure");        }         /* If we get here we need to grow the output buffer and try again */        out_ofs = out_maxlen - strm->avail_out;        if (strm->avail_in) {            grow_size = strm->avail_in * 8;        } else {            /* Not sure how much to grow by */            grow_size = 32;        }        out_maxlen += grow_size;         if ((out_maxlen > (int) payload_limit) && limiter++) {            LIBSSH2_FREE(session, out);            return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,                                  "Excessive growth in decompression phase");        }         newout = LIBSSH2_REALLOC(session, out, out_maxlen);        if (!newout) {            LIBSSH2_FREE(session, out);            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,                                  "Unable to expand decompression buffer");        }        out = newout;        strm->next_out = (unsigned char *) out + out_ofs;        strm->avail_out += grow_size;    }     *dest = (unsigned char *) out;    *dest_len = out_maxlen - strm->avail_out;     return 0;}  /* libssh2_comp_method_zlib_dtor * All done, no more compression for you */static intcomp_method_zlib_dtor(LIBSSH2_SESSION *session, int compr, void **abstract){    z_stream *strm = *abstract;     if (strm) {        if (compr)            deflateEnd(strm);        else            inflateEnd(strm);        LIBSSH2_FREE(session, strm);    }     *abstract = NULL;    return 0;} static const LIBSSH2_COMP_METHOD comp_method_zlib = {    "zlib",    1, /* yes, this compresses */    1, /* do compression during userauth */    comp_method_zlib_init,    comp_method_zlib_comp,    comp_method_zlib_decomp,    comp_method_zlib_dtor,}; static const LIBSSH2_COMP_METHOD comp_method_zlib_openssh = {    "zlib@openssh.com",    1, /* yes, this compresses */    0, /* don't use compression during userauth */    comp_method_zlib_init,    comp_method_zlib_comp,    comp_method_zlib_decomp,    comp_method_zlib_dtor,};#endif /* LIBSSH2_HAVE_ZLIB */ /* If compression is enabled by the API, then this array is used which then   may allow compression if zlib is available at build time */static const LIBSSH2_COMP_METHOD *comp_methods[] = {#ifdef LIBSSH2_HAVE_ZLIB    &comp_method_zlib,    &comp_method_zlib_openssh,#endif /* LIBSSH2_HAVE_ZLIB */    &comp_method_none,    NULL}; /* If compression is disabled by the API, then this array is used */static const LIBSSH2_COMP_METHOD *no_comp_methods[] = {    &comp_method_none,    NULL}; const LIBSSH2_COMP_METHOD **_libssh2_comp_methods(LIBSSH2_SESSION *session){    if(session->flag.compress)        return comp_methods;    else        return no_comp_methods;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t