1diff -Naur mindbright/Makefile mindbright-compression/Makefile 2--- mindbright/Makefile Tue Aug 1 20:37:08 2000 3+++ mindbright-compression/Makefile Tue Dec 19 05:49:00 2000 4@@ -56,6 +56,7 @@ 5 ssh/SSHTxChannel.class \ 6 ssh/SSHTunnel.class \ 7 ssh/SSHProtocolPlugin.class \ 8+ ssh/SSHCompression.class \ 9 ssh/SSHPdu.class \ 10 ssh/SSHDataInputStream.class \ 11 ssh/SSHDataOutputStream.class \ 12diff -Naur mindbright/ssh/SSH.java mindbright-compression/ssh/SSH.java 13--- mindbright/ssh/SSH.java Tue Aug 1 22:30:52 2000 14+++ mindbright-compression/ssh/SSH.java Tue Dec 19 05:59:45 2000 15@@ -206,6 +206,8 @@ 16 protected Cipher rcvCipher; 17 protected int cipherType; 18 19+ protected static int compressionLevel=0; 20+ 21 // Server data fields 22 // 23 protected byte[] srvCookie; 24diff -Naur mindbright/ssh/SSHClient.java mindbright-compression/ssh/SSHClient.java 25--- mindbright/ssh/SSHClient.java Tue Apr 4 09:34:12 2000 26+++ mindbright-compression/ssh/SSHClient.java Tue Dec 19 05:31:57 2000 27@@ -481,6 +481,10 @@ 28 protected void disconnect(boolean graceful) { 29 if(!isConnected) 30 return; 31+ if(SSH.compressionLevel!=0){ 32+ SSHCompression.uninit(); 33+ SSH.compressionLevel=0; 34+ } 35 isConnected = false; 36 isOpened = false; 37 gracefulExit = graceful; 38@@ -897,7 +901,7 @@ 39 void initiateSession() throws IOException { 40 // !!! java.util.zip.Deflater/Inflater can't be used since we can't give 41 // the native inflate/deflate methods the Z_PARTIAL_FLUSH flag 42- // requestCompression(3); 43+ requestCompression(user.getCompressionLevel()); 44 45 if(user.wantPTY()) 46 requestPTY(); 47@@ -939,11 +943,20 @@ 48 } 49 50 void requestCompression(int level) throws IOException { 51+ if(level==0) return; 52+ if(level<0 || level>9){ 53+ if(interactor!=null) 54+ interactor.report("Error requesting invalid compression level: " + level); 55+ return; 56+ } 57+ 58 SSHPduOutputStream outpdu = new SSHPduOutputStream(CMSG_REQUEST_COMPRESSION, sndCipher); 59 outpdu.writeInt(level); 60 outpdu.writeTo(sshOut); 61 if(!isSuccess() && interactor != null) 62 interactor.report("Error requesting compression level: " + level); 63+ SSH.compressionLevel=level; 64+ SSHCompression.init(level); 65 } 66 67 void requestMaxPacketSz(int sz) throws IOException { 68diff -Naur mindbright/ssh/SSHClientUser.java mindbright-compression/ssh/SSHClientUser.java 69--- mindbright/ssh/SSHClientUser.java Sat Feb 26 12:28:51 2000 70+++ mindbright-compression/ssh/SSHClientUser.java Mon Dec 18 05:23:28 2000 71@@ -30,6 +30,7 @@ 72 public String getDisplay(); 73 public int getMaxPacketSz(); 74 public int getAliveInterval(); 75+ public int getCompressionLevel(); 76 77 public boolean wantX11Forward(); 78 public boolean wantPrivileged(); 79diff -Naur mindbright/ssh/SSHClientUserAdaptor.java mindbright-compression/ssh/SSHClientUserAdaptor.java 80--- mindbright/ssh/SSHClientUserAdaptor.java Sat Feb 26 12:28:51 2000 81+++ mindbright-compression/ssh/SSHClientUserAdaptor.java Mon Dec 18 06:07:33 2000 82@@ -62,6 +62,10 @@ 83 return 0; 84 } 85 86+ public int getCompressionLevel() { 87+ return 0; 88+ } 89+ 90 public boolean wantX11Forward() { 91 return false; 92 } 93diff -Naur mindbright/ssh/SSHCompression.java mindbright-compression/ssh/SSHCompression.java 94--- mindbright/ssh/SSHCompression.java Thu Jan 1 00:00:00 1970 95+++ mindbright-compression/ssh/SSHCompression.java Wed Dec 20 03:13:52 2000 96@@ -0,0 +1,145 @@ 97+/****************************************************************************** 98+ * 99+ * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden. 100+ * www.mindbright.se, info@mindbright.se 101+ * 102+ * This program is free software; you can redistribute it and/or modify 103+ * it under the terms of the GNU General Public License as published by 104+ * the Free Software Foundation; either version 2 of the License, or 105+ * (at your option) any later version. 106+ * 107+ * This program is distributed in the hope that it will be useful, 108+ * but WITHOUT ANY WARRANTY; without even the implied warranty of 109+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 110+ * GNU General Public License for more details. 111+ * 112+ ***************************************************************************** 113+ * $Author: ymnk@jcraft.com $ 114+ * $Date: 2000/12/18 17:13:50 $ 115+ * $Name: rel0-0-0 $ 116+ *****************************************************************************/ 117+package mindbright.ssh; 118+ 119+import mindbright.ssh.*; 120+import com.jcraft.jzlib.*; 121+ 122+final class SSHCompression{ 123+ static private ZStream deflate_stream=null; 124+ static private ZStream inflate_stream=null; 125+ 126+ static void init(int level){ 127+ deflate_stream=new ZStream(); 128+ inflate_stream=new ZStream(); 129+ deflate_stream.deflateInit(level); 130+ inflate_stream.inflateInit(); 131+ } 132+ 133+ static void uninit(){ 134+ if(SSH.DEBUGMORE){ 135+ if(deflate_stream!=null) 136+ System.out.println("compress outgoing: raw data "+deflate_stream.total_in+ 137+ ", compressed "+deflate_stream.total_out+ 138+ ", factor "+(deflate_stream.total_in == 0 ? 139+ 0.0 : 140+ ((double)deflate_stream.total_out) / 141+ ((double)deflate_stream.total_in))); 142+ if(inflate_stream!=null) 143+ System.out.println("compress incoming: raw data "+inflate_stream.total_out+ 144+ ", compressed "+inflate_stream.total_in+ 145+ ", factor "+(inflate_stream.total_out == 0 ? 146+ 0.0 : 147+ ((double)inflate_stream.total_in) / 148+ ((double)inflate_stream.total_out))); 149+ } 150+ if(deflate_stream!=null){ 151+ deflate_stream.deflateEnd(); 152+ deflate_stream.free(); 153+ deflate_stream=null; 154+ } 155+ if(inflate_stream!=null){ 156+ inflate_stream.inflateEnd(); 157+ inflate_stream.free(); 158+ inflate_stream=null; 159+ } 160+ } 161+ 162+ static private final int BUF_SIZE=4096; 163+ static private byte[] d_buf=new byte[BUF_SIZE]; 164+ static private byte[] i_buf=new byte[BUF_SIZE]; 165+ 166+ static int compress(byte[] buf, int len){ 167+ 168+ deflate_stream.next_in=buf; 169+ deflate_stream.next_in_index=8; 170+ deflate_stream.avail_in=len-8; 171+ 172+ int status; 173+ int outputlen=8; 174+ 175+ do{ 176+ deflate_stream.next_out=d_buf; 177+ deflate_stream.next_out_index=0; 178+ deflate_stream.avail_out=BUF_SIZE; 179+ status=deflate_stream.deflate(JZlib.Z_PARTIAL_FLUSH); 180+ switch(status){ 181+ case JZlib.Z_OK: 182+ System.arraycopy(d_buf, 0, 183+ buf, outputlen, 184+ BUF_SIZE-deflate_stream.avail_out); 185+ outputlen+=(BUF_SIZE-deflate_stream.avail_out); 186+ break; 187+ default: 188+ System.err.println("SSHCompression.compress: deflate returnd "+status); 189+ } 190+ } 191+ while(deflate_stream.avail_out==0); 192+ return outputlen; 193+ } 194+ 195+ static private byte[] out_buf = new byte[BUF_SIZE]; 196+ static void uncompress(SSHPduInputStream input){ 197+ int pad=(8-(input.length%8)); 198+ int out_end=0; 199+ 200+ inflate_stream.next_in=input.bytes; 201+ inflate_stream.next_in_index=pad; 202+ inflate_stream.avail_in=input.length - 4; // chop checksum field 203+ 204+ while(true){ 205+ inflate_stream.next_out=i_buf; 206+ inflate_stream.next_out_index=0; 207+ inflate_stream.avail_out=BUF_SIZE; 208+ 209+ int status=inflate_stream.inflate(JZlib.Z_PARTIAL_FLUSH); 210+ switch(status){ 211+ case JZlib.Z_OK: 212+ if(out_buf.length<out_end+BUF_SIZE-inflate_stream.avail_out){ 213+ byte[] foo=new byte[out_end+BUF_SIZE-inflate_stream.avail_out]; 214+ System.arraycopy(out_buf, 0, foo, 0, out_end); 215+ out_buf=foo; 216+ } 217+ System.arraycopy(i_buf, 0, 218+ out_buf, out_end, 219+ BUF_SIZE-inflate_stream.avail_out); 220+ out_end+=(BUF_SIZE-inflate_stream.avail_out); 221+ break; 222+ case JZlib.Z_BUF_ERROR: 223+ if(out_end>input.bytes.length){ 224+ byte[] foo=new byte[out_end]; 225+ System.arraycopy(out_buf, 0, foo, 0, out_end); 226+ input.bytes=foo; 227+ } 228+ else{ 229+ System.arraycopy(out_buf, 0, input.bytes, 0, out_end); 230+ } 231+ input.length=out_end; 232+ try{ input.reset(); } 233+ catch(Exception e){} 234+ return; 235+ default: 236+ System.err.println("SSHCompression.uncompress: inflate returnd "+status); 237+ return; // humm.. 238+ } 239+ } 240+ } 241+} 242diff -Naur mindbright/ssh/SSHMenuHandlerFull.java mindbright-compression/ssh/SSHMenuHandlerFull.java 243--- mindbright/ssh/SSHMenuHandlerFull.java Tue Aug 1 20:37:08 2000 244+++ mindbright-compression/ssh/SSHMenuHandlerFull.java Tue Dec 19 05:26:02 2000 245@@ -544,6 +544,7 @@ 246 247 Dialog settingsDialog = null; 248 Choice choiceCipher, choiceAuthTyp; 249+ Choice choiceCompressionLevel; 250 Checkbox cbX11, cbPrvPrt, cbRemFwd, cbIdHost, cbPortFtp, cbLocHst, cbMTU, cbAlive, cbForcPty; 251 TextField textPort, textUser, textId, textDisp, textMtu, textAlive, textSrv, 252 textRealAddr, textAuthList, textLocHost; 253@@ -801,6 +802,17 @@ 254 grid2.setConstraints(cbRemFwd, gridc2); 255 ap.add(cbRemFwd); 256 257+ gridc2.gridy = 7; 258+ lbl = new Label("CompressionLevel:"); 259+ grid2.setConstraints(lbl, gridc2); 260+ ap.add(lbl); 261+ choiceCompressionLevel = new Choice(); 262+ for(i = 0; i < 10; i++) { 263+ choiceCompressionLevel.add(new Integer(i).toString()); 264+ } 265+ grid2.setConstraints(choiceCompressionLevel, gridc2); 266+ ap.add(choiceCompressionLevel); 267+ 268 gridc.gridy = 7; 269 gridc.insets = new Insets(0, 0, 0, 0); 270 gridc.anchor = GridBagConstraints.CENTER; 271@@ -844,6 +856,8 @@ 272 } else { 273 client.propsHandler.setProperty("authtyp", authType); 274 } 275+ String level = choiceCompressionLevel.getSelectedItem(); 276+ client.propsHandler.setProperty("compression", level); 277 client.propsHandler.setProperty("port", textPort.getText()); 278 client.propsHandler.setProperty("usrname", textUser.getText()); 279 client.propsHandler.setProperty("cipher", cipher[choiceCipher.getSelectedIndex()]); 280@@ -924,6 +938,9 @@ 281 choiceAuthTyp.select("custom..."); 282 textAuthList.setText(at); 283 } 284+ 285+ at = client.propsHandler.getProperty("compression"); 286+ choiceCompressionLevel.select(at); 287 288 textId.setText(client.propsHandler.getProperty("idfile")); 289 290diff -Naur mindbright/ssh/SSHPduInputStream.java mindbright-compression/ssh/SSHPduInputStream.java 291--- mindbright/ssh/SSHPduInputStream.java Mon Jul 19 17:13:50 1999 292+++ mindbright-compression/ssh/SSHPduInputStream.java Tue Dec 19 05:32:08 2000 293@@ -102,6 +102,17 @@ 294 throw new IOException("Invalid checksum in packet"); 295 296 this.skip(8 - (len % 8)); 297+ 298+ if(SSH.compressionLevel!=0){ 299+ //System.out.print("readFrom: length="+length); 300+ byte[] foo=bytes; 301+ SSHCompression.uncompress(this); 302+ if(foo!=bytes){ 303+ this.in = new PduByteArrayInputStream(bytes); 304+ } 305+ //System.out.println(" -> length="+length); 306+ } 307+ 308 type = (int)this.readByte(); 309 310 if(type == SSH.MSG_DEBUG) { 311diff -Naur mindbright/ssh/SSHPduOutputStream.java mindbright-compression/ssh/SSHPduOutputStream.java 312--- mindbright/ssh/SSHPduOutputStream.java Mon Jul 19 17:13:50 1999 313+++ mindbright-compression/ssh/SSHPduOutputStream.java Tue Dec 19 05:32:14 2000 314@@ -126,6 +126,13 @@ 315 int padSz; 316 int off = 0; 317 318+ if(SSH.compressionLevel!=0){ 319+ //System.out.print("writeTo: size="+bytes.size()); 320+ int size=SSHCompression.compress(bytes.getBuf(), bytes.size()); 321+ bytes.setCount(size); 322+ //System.out.println(" -> size="+bytes.size()); 323+ } 324+ 325 iSz = bytes.size(); 326 pad = (iSz + 4) % 8; 327 crc32 = (int)CRC32.getValue(bytes.getBuf(), pad, iSz - pad); 328diff -Naur mindbright/ssh/SSHPropertyHandler.java mindbright-compression/ssh/SSHPropertyHandler.java 329--- mindbright/ssh/SSHPropertyHandler.java Tue Aug 1 20:37:08 2000 330+++ mindbright-compression/ssh/SSHPropertyHandler.java Tue Dec 19 05:23:39 2000 331@@ -84,6 +84,7 @@ 332 { "secrand", "0", "level of security in random seed (for generating session key)", 333 "(0-2, 0=low and 2=high)" }, 334 { "alive", "0", "Connection keep-alive interval in seconds (0 means none)", "(0-600)" }, 335+ { "compression", "0", "Compression Level (0 means none, 1=fast, 9=slow,best )", "(0-9)" }, 336 { "x11fwd", "false", "indicates whether X11 display is forwarded or not", "(true/false)" }, 337 { "prvport", "false", "indicates whether to use a privileged port or not (locally)", "(true/false)" }, 338 { "forcpty", "true", "indicates whether to allocate a pty or not", "(true/false)" }, 339@@ -295,7 +296,7 @@ 340 if(!(value.equals("true") || value.equals("false"))) 341 throw new IllegalArgumentException("Value for " + key + " must be 'true' or 'false'"); 342 // 343- } else if(key.equals("port") || key.equals("proxyport") || key.equals("mtu") || 344+ } else if(key.equals("port") || key.equals("proxyport") || key.equals("mtu") || key.equals("compression") || 345 key.equals("secrand") || key.equals("alive")) { 346 try { 347 int val = Integer.valueOf(value).intValue(); 348@@ -309,6 +310,9 @@ 349 } else if(key.equals("secrand")) { 350 if(val < 0 || val > 2) 351 throw new IllegalArgumentException("Secrand must be 0-2"); 352+ } else if(key.equals("compression")) { 353+ if(val < 0 || val > 9) 354+ throw new IllegalArgumentException("Compression Level must be 0-9"); 355 } 356 } catch (NumberFormatException e) { 357 throw new IllegalArgumentException("Value for " + key + " must be an integer"); 358@@ -1203,6 +1207,10 @@ 359 360 public int getAliveInterval() { 361 return Integer.valueOf(getProperty("alive")).intValue(); 362+ } 363+ 364+ public int getCompressionLevel() { 365+ return Integer.valueOf(getProperty("compression")).intValue(); 366 } 367 368 public boolean wantX11Forward() { 369