1 2 29 30 package com.jcraft.jhttptunnel; 31 32 import java.io.*; 33 34 public class JHttpTunnelClient{ 35 static final private int CONTENT_LENGTH=1024*10; 37 38 private boolean init=false; 39 private boolean closed=false; 40 41 private String dest_host=null; 42 private int dest_port=0; 43 private Proxy proxy=null; 44 45 private InBound ib=null; 46 private OutBound ob=null; 47 48 50 public JHttpTunnelClient(String host, int port){ 51 this.dest_host=host; 52 this.dest_port=port; 53 } 54 public void setProxy(String host, int port){ 55 this.proxy=new Proxy(host, port); 56 } 57 58 public void connect() throws JHttpTunnelException{ 59 60 if(ib==null){ 61 68 throw new JHttpTunnelException("InBound is not given"); 69 } 70 ib.setHost(dest_host); 71 ib.setPort(dest_port); 72 ib.setProxy(proxy); 73 74 if(ob==null){ 75 82 throw new JHttpTunnelException("OutBound is not given"); 83 } 84 ob.setHost(dest_host); 85 ob.setPort(dest_port); 86 ob.setProxy(proxy); 87 ob.setContentLength(CONTENT_LENGTH); 88 89 try{ 90 getOutbound(); 91 getInbound(); 92 } 93 catch(Exception e){ 94 throw new JHttpTunnelException(e.toString()); 95 } 96 } 97 98 private void getOutbound() throws IOException{ 99 if(closed){ 101 throw new IOException("broken pipe"); 102 } 103 ob.connect(); 104 if(!init){ 105 openChannel(1); 106 init=true; 107 } 108 } 109 110 private void getInbound() throws IOException{ 111 ib.connect(); 113 } 114 115 private byte[] command=new byte[4]; 116 public void openChannel(int i) throws IOException{ 117 command[0]=JHttpTunnel.TUNNEL_OPEN; 118 command[1]=0; 119 command[2]=1; 120 command[3]=0; 121 ob.sendData(command, 0, 4, true); 122 } 123 public void sendDisconnect() throws IOException{ 124 command[0]=JHttpTunnel.TUNNEL_DISCONNECT; 126 ob.sendData(command, 0, 1, true); 127 } 128 public void sendClose() throws IOException{ 129 command[0]=JHttpTunnel.TUNNEL_CLOSE; 131 ob.sendData(command, 0, 1, true); 132 } 133 public void sendPad1(boolean flush) throws IOException{ 134 command[0]=JHttpTunnel.TUNNEL_PAD1; 135 ob.sendData(command, 0, 1, flush); 136 } 137 public void write(byte[] foo, int s, int l) throws IOException{ 138 140 if(l<=0) return; 141 142 if(ob.sendCount<=4){ 143 if(0<ob.sendCount){ 145 while(ob.sendCount>1){ 146 sendPad1(false); 147 } 148 sendDisconnect(); 149 } 150 getOutbound(); 151 } 152 153 while((ob.sendCount-1-3)<l){ 154 int len=(ob.sendCount-1-3); 155 command[0]=JHttpTunnel.TUNNEL_DATA; 156 command[1]=(byte)((len>>>8)&0xff); 157 command[2]=(byte)(len&0xff); 158 ob.sendData(command, 0, 3, true); 160 ob.sendData(foo, s, len, true); 161 s+=len; 162 l-=len; 163 164 166 sendDisconnect(); 167 if(l>0){ 168 getOutbound(); 169 } 170 } 171 if(l<=0)return; 172 173 command[0]=JHttpTunnel.TUNNEL_DATA; 174 command[1]=(byte)((l>>>8)&0xff); 175 command[2]=(byte)(l&0xff); 176 ob.sendData(command, 0, 3, false); 177 ob.sendData(foo, s, l, true); 178 } 179 180 int buf_len=0; 181 public int read(byte[] foo, int s, int l) throws IOException{ 182 if(closed)return -1; 183 184 try{ 185 if(buf_len>0){ 186 int len=buf_len; 187 if(l<buf_len){ 188 len=l; 189 } 190 int i=ib.receiveData(foo, s, len); 191 buf_len-=i; 192 return i; 193 } 194 195 int len=0; 196 while(!closed){ 197 int i=ib.receiveData(foo, s, 1); 198 if(i<=0){ 199 return -1; 200 } 201 int request=foo[s]&0xff; 202 if((request&JHttpTunnel.TUNNEL_SIMPLE)==0){ 204 i=ib.receiveData(foo, s, 1); 205 len=(((foo[s])<<8)&0xff00); 206 i=ib.receiveData(foo, s, 1); 207 len=len|(foo[s]&0xff); 208 } 209 switch(request){ 211 case JHttpTunnel.TUNNEL_DATA: 212 buf_len=len; 213 if(l<buf_len){ 215 len=l; 216 } 217 int orgs=s; 218 while(len>0){ 219 i=ib.receiveData(foo, s, len); 220 if(i<0)break; 221 buf_len-=i; 222 s+=i; 223 len-=i; 224 } 225 return s-orgs; 227 case JHttpTunnel.TUNNEL_PADDING: 228 ib.receiveData(null, 0, len); 229 continue; 230 case JHttpTunnel.TUNNEL_ERROR: 231 byte[] error=new byte[len]; 232 ib.receiveData(error, 0, len); 233 throw new IOException("JHttpTunnel: "+new String (error, 0, len)); 235 case JHttpTunnel.TUNNEL_PAD1: 236 continue; 237 case JHttpTunnel.TUNNEL_CLOSE: 238 closed=true; 239 break; 242 case JHttpTunnel.TUNNEL_DISCONNECT: 243 continue; 245 default: 246 throw new IOException("JHttpTunnel: protocol error 0x"+Integer.toHexString(request&0xff)); 249 } 250 } 251 } 252 catch(IOException e){ 253 throw e; 254 } 255 catch(Exception e){ 256 } 258 return -1; 259 } 260 261 private InputStream in=null; 262 public InputStream getInputStream(){ 263 if(in!=null) return in; 264 in= 265 new InputStream(){ 266 byte[] tmp=new byte[1]; 267 public int read() throws IOException{ 268 int i=JHttpTunnelClient.this.read(tmp, 0, 1); 269 return (i==-1?-1:tmp[0]); 270 } 271 public int read(byte[] foo) throws IOException{ 272 return JHttpTunnelClient.this.read(foo, 0, foo.length); 273 } 274 public int read(byte[] foo, int s, int l) throws IOException{ 275 return JHttpTunnelClient.this.read(foo, s, l); 276 } 277 }; 278 return in; 279 } 280 281 private OutputStream out=null; 282 public OutputStream getOutputStream(){ 283 if(out!=null) return out; 284 out= 285 new OutputStream(){ 286 final byte[] tmp=new byte[1]; 287 public void write(int foo) throws IOException{ 288 tmp[0]=(byte)foo; 289 JHttpTunnelClient.this.write(tmp, 0, 1); 290 } 291 public void write(byte[] foo) throws IOException{ 292 JHttpTunnelClient.this.write(foo, 0, foo.length); 293 } 294 public void write(byte[] foo, int s, int l) throws IOException{ 295 JHttpTunnelClient.this.write(foo, s, l); 296 } 297 }; 298 return out; 299 } 300 301 public void close(){ 302 try{sendClose();}catch(Exception e){} 304 try{ib.close();}catch(Exception e){} 305 try{ob.close();}catch(Exception e){} 306 closed=true; 307 } 308 309 public void setInBound(InBound ib){ this.ib=ib; } 310 public void setOutBound(OutBound ob){ this.ob=ob; } 311 312 424 } 425 | Popular Tags |