1 /* gzip.c */ 2 /* include hooks for compression of packets */ 3 /* 4 Copyright 2003 Aris Adamantiadis 5 6 This file is part of the SSH Library 7 8 The SSH Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 2.1 of the License, or (at your 11 option) any later version. 12 13 The SSH Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the SSH Library; see the file COPYING. If not, write to 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 21 MA 02111-1307, USA. */ 22 #include "libssh/priv.h" 23 #ifdef HAVE_LIBZ 24 #undef NO_GZIP 25 #else 26 #define NO_GZIP 27 #endif 28 29 #ifndef NO_GZIP 30 #include <zlib.h> 31 #include <string.h> 32 #define BLOCKSIZE 4092 33 34 static z_stream *initcompress(SSH_SESSION *session,int level){ 35 z_stream *stream=malloc(sizeof(z_stream)); 36 int status; 37 memset(stream,0,sizeof(z_stream)); 38 status=deflateInit(stream,level); 39 if (status!=0) 40 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"status %d inititalising zlib deflate",status); 41 return stream; 42 } 43 44 BUFFER *gzip_compress(SSH_SESSION *session,BUFFER *source,int level){ 45 BUFFER *dest; 46 static unsigned char out_buf[BLOCKSIZE]; 47 void *in_ptr=buffer_get(source); 48 unsigned long in_size=buffer_get_len(source); 49 unsigned long len; 50 int status; 51 z_stream *zout=session->current_crypto->compress_out_ctx; 52 if(!zout) 53 zout=session->current_crypto->compress_out_ctx=initcompress(session,level); 54 dest=buffer_new(); 55 zout->next_out=out_buf; 56 zout->next_in=in_ptr; 57 zout->avail_in=in_size; 58 do { 59 zout->avail_out=BLOCKSIZE; 60 status=deflate(zout,Z_PARTIAL_FLUSH); 61 if(status !=0){ 62 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"status %d deflating zlib packet",status); 63 return NULL; 64 } 65 len=BLOCKSIZE-zout->avail_out; 66 buffer_add_data(dest,out_buf,len); 67 zout->next_out=out_buf; 68 } while (zout->avail_out == 0); 69 70 return dest; 71 } 72 73 int compress_buffer(SSH_SESSION *session,BUFFER *buf){ 74 BUFFER *dest=gzip_compress(session,buf,9); 75 if(!dest) 76 return -1; 77 buffer_reinit(buf); 78 buffer_add_data(buf,buffer_get(dest),buffer_get_len(dest)); 79 buffer_free(dest); 80 return 0; 81 } 82 83 /* decompression */ 84 85 static z_stream *initdecompress(SSH_SESSION *session){ 86 z_stream *stream=malloc(sizeof(z_stream)); 87 int status; 88 memset(stream,0,sizeof(z_stream)); 89 status=inflateInit(stream); 90 if (status!=0){ 91 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"Status = %d initiating inflate context !",status); 92 free(stream); 93 stream=NULL; 94 } 95 return stream; 96 } 97 98 BUFFER *gzip_decompress(SSH_SESSION *session,BUFFER *source){ 99 BUFFER *dest; 100 static unsigned char out_buf[BLOCKSIZE]; 101 void *in_ptr=buffer_get_rest(source); 102 unsigned long in_size=buffer_get_rest_len(source); 103 unsigned long len; 104 int status; 105 z_stream *zin=session->current_crypto->compress_in_ctx; 106 if(!zin) 107 zin=session->current_crypto->compress_in_ctx=initdecompress(session); 108 dest=buffer_new(); 109 zin->next_out=out_buf; 110 zin->next_in=in_ptr; 111 zin->avail_in=in_size; 112 do { 113 zin->avail_out=BLOCKSIZE; 114 status=inflate(zin,Z_PARTIAL_FLUSH); 115 if(status !=Z_OK){ 116 ssh_set_error((session->connected?session:NULL),SSH_FATAL,"status %d inflating zlib packet",status); 117 buffer_free(dest); 118 return NULL; 119 } 120 len=BLOCKSIZE-zin->avail_out; 121 buffer_add_data(dest,out_buf,len); 122 zin->next_out=out_buf; 123 } while (zin->avail_out == 0); 124 125 return dest; 126 } 127 128 int decompress_buffer(SSH_SESSION *session,BUFFER *buf){ 129 BUFFER *dest=gzip_decompress(session,buf); 130 buffer_reinit(buf); 131 if(!dest){ 132 return -1; /* failed */ 133 } 134 buffer_reinit(buf); 135 buffer_add_data(buf,buffer_get(dest),buffer_get_len(dest)); 136 buffer_free(dest); 137 return 0; 138 } 139 140 #endif /* NO_GZIP */ |