1 2 29 30 package com.jcraft.jsch; 31 32 import java.io.PipedInputStream ; 33 import java.io.PipedOutputStream ; 34 import java.io.InputStream ; 35 import java.io.OutputStream ; 36 import java.io.IOException ; 37 38 39 public abstract class Channel implements Runnable { 40 41 static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION= 91; 42 static final int SSH_MSG_CHANNEL_OPEN_FAILURE= 92; 43 44 static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED= 1; 45 static final int SSH_OPEN_CONNECT_FAILED= 2; 46 static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE= 3; 47 static final int SSH_OPEN_RESOURCE_SHORTAGE= 4; 48 49 static int index=0; 50 private static java.util.Vector pool=new java.util.Vector (); 51 static Channel getChannel(String type){ 52 if(type.equals("session")){ 53 return new ChannelSession(); 54 } 55 if(type.equals("shell")){ 56 return new ChannelShell(); 57 } 58 if(type.equals("exec")){ 59 return new ChannelExec(); 60 } 61 if(type.equals("x11")){ 62 return new ChannelX11(); 63 } 64 if(type.equals("auth-agent@openssh.com")){ 65 return new ChannelAgentForwarding(); 66 } 67 if(type.equals("direct-tcpip")){ 68 return new ChannelDirectTCPIP(); 69 } 70 if(type.equals("forwarded-tcpip")){ 71 return new ChannelForwardedTCPIP(); 72 } 73 if(type.equals("sftp")){ 74 return new ChannelSftp(); 75 } 76 if(type.equals("subsystem")){ 77 return new ChannelSubsystem(); 78 } 79 return null; 80 } 81 static Channel getChannel(int id, Session session){ 82 synchronized(pool){ 83 for(int i=0; i<pool.size(); i++){ 84 Channel c=(Channel)(pool.elementAt(i)); 85 if(c.id==id && c.session==session) return c; 86 } 87 } 88 return null; 89 } 90 static void del(Channel c){ 91 synchronized(pool){ 92 pool.removeElement(c); 93 } 94 } 95 96 int id; 97 int recipient=-1; 98 byte[] type="foo".getBytes(); 99 int lwsize_max=0x100000; 100 int lwsize=lwsize_max; int lmpsize=0x4000; 105 int rwsize=0; int rmpsize=0; 108 IO io=null; 109 Thread thread=null; 110 111 boolean eof_local=false; 112 boolean eof_remote=false; 113 114 boolean close=false; 115 boolean connected=false; 116 117 int exitstatus=-1; 118 119 int reply=0; 120 int connectTimeout=0; 121 122 Session session; 123 124 Channel(){ 125 synchronized(pool){ 126 id=index++; 127 pool.addElement(this); 128 } 129 } 130 void setRecipient(int foo){ 131 this.recipient=foo; 132 } 133 int getRecipient(){ 134 return recipient; 135 } 136 137 void init(){ 138 } 139 140 public void connect() throws JSchException{ 141 connect(0); 142 } 143 144 public void connect(int connectTimeout) throws JSchException{ 145 if(!session.isConnected()){ 146 throw new JSchException("session is down"); 147 } 148 this.connectTimeout=connectTimeout; 149 try{ 150 Buffer buf=new Buffer(100); 151 Packet packet=new Packet(buf); 152 packet.reset(); 159 buf.putByte((byte)90); 160 buf.putString(this.type); 161 buf.putInt(this.id); 162 buf.putInt(this.lwsize); 163 buf.putInt(this.lmpsize); 164 session.write(packet); 165 int retry=1000; 166 long start=System.currentTimeMillis(); 167 long timeout=connectTimeout; 168 while(this.getRecipient()==-1 && 169 session.isConnected() && 170 retry>0){ 171 if(timeout>0L){ 172 if((System.currentTimeMillis()-start)>timeout){ 173 retry=0; 174 continue; 175 } 176 } 177 try{Thread.sleep(50);}catch(Exception ee){} 178 retry--; 179 } 180 if(!session.isConnected()){ 181 throw new JSchException("session is down"); 182 } 183 if(retry==0){ 184 throw new JSchException("channel is not opened."); 185 } 186 connected=true; 187 start(); 188 } 189 catch(Exception e){ 190 connected=false; 191 if(e instanceof JSchException) throw (JSchException)e; 192 } 193 } 194 195 public void setXForwarding(boolean foo){ 196 } 197 198 public void start() throws JSchException{} 199 200 public boolean isEOF() {return eof_remote;} 201 202 void getData(Buffer buf){ 203 setRecipient(buf.getInt()); 204 setRemoteWindowSize(buf.getInt()); 205 setRemotePacketSize(buf.getInt()); 206 } 207 208 public void setInputStream(InputStream in){ 209 io.setInputStream(in, false); 210 } 211 public void setInputStream(InputStream in, boolean dontclose){ 212 io.setInputStream(in, dontclose); 213 } 214 public void setOutputStream(OutputStream out){ 215 io.setOutputStream(out, false); 216 } 217 public void setOutputStream(OutputStream out, boolean dontclose){ 218 io.setOutputStream(out, dontclose); 219 } 220 public void setExtOutputStream(OutputStream out){ 221 io.setExtOutputStream(out, false); 222 } 223 public void setExtOutputStream(OutputStream out, boolean dontclose){ 224 io.setExtOutputStream(out, dontclose); 225 } 226 public InputStream getInputStream() throws IOException { 227 PipedInputStream in= 228 new MyPipedInputStream( 229 32*1024 ); 231 io.setOutputStream(new PassiveOutputStream(in), false); 232 return in; 233 } 234 public InputStream getExtInputStream() throws IOException { 235 PipedInputStream in= 236 new MyPipedInputStream( 237 32*1024 ); 239 io.setExtOutputStream(new PassiveOutputStream(in), false); 240 return in; 241 } 242 public OutputStream getOutputStream() throws IOException { 243 250 251 final Channel channel=this; 252 OutputStream out=new OutputStream (){ 253 private int dataLen=0; 254 private Buffer buffer=null; 255 private Packet packet=null; 256 private boolean closed=false; 257 private void init(){ 258 buffer=new Buffer(rmpsize); 259 packet=new Packet(buffer); 260 } 261 byte[] b=new byte[1]; 262 public void write(int w) throws java.io.IOException { 263 b[0]=(byte)w; 264 write(b, 0, 1); 265 } 266 public void write(byte[] buf, int s, int l) throws java.io.IOException { 267 if(packet==null){ 268 init(); 269 } 270 271 if(closed){ 272 throw new java.io.IOException ("Already closed"); 273 } 274 275 byte[] _buf=buffer.buffer; 276 int _bufl=_buf.length; 277 while(l>0){ 278 int _l=l; 279 if(l>_bufl-(14+dataLen)-32-20){ 280 _l=_bufl-(14+dataLen)-32-20; 281 } 282 283 if(_l<=0){ 284 flush(); 285 continue; 286 } 287 288 System.arraycopy(buf, s, _buf, 14+dataLen, _l); 289 dataLen+=_l; 290 s+=_l; 291 l-=_l; 292 } 293 } 294 295 public void flush() throws java.io.IOException { 296 if(closed){ 297 throw new java.io.IOException ("Already closed"); 298 } 299 if(dataLen==0) 300 return; 301 packet.reset(); 302 buffer.putByte((byte)Session.SSH_MSG_CHANNEL_DATA); 303 buffer.putInt(recipient); 304 buffer.putInt(dataLen); 305 buffer.skip(dataLen); 306 try{ 307 int foo=dataLen; 308 dataLen=0; 309 session.write(packet, channel, foo); 310 } 311 catch(Exception e){ 312 close(); 313 throw new java.io.IOException (e.toString()); 314 } 315 316 } 317 public void close() throws java.io.IOException { 318 if(packet==null){ 319 init(); 320 } 321 if(closed){ 322 return; 323 } 324 if(dataLen>0){ 325 flush(); 326 } 327 channel.eof(); 328 closed=true; 329 } 330 }; 331 return out; 332 333 } 334 class MyPipedInputStream extends PipedInputStream { 335 MyPipedInputStream() throws IOException { super(); } 336 MyPipedInputStream(int size) throws IOException { 337 super(); 338 buffer=new byte[size]; 339 } 340 MyPipedInputStream(PipedOutputStream out) throws IOException { super(out); } 341 MyPipedInputStream(PipedOutputStream out, int size) throws IOException { 342 super(out); 343 buffer=new byte[size]; 344 } 345 } 346 void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; } 347 void setLocalWindowSize(int foo){ this.lwsize=foo; } 348 void setLocalPacketSize(int foo){ this.lmpsize=foo; } 349 synchronized void setRemoteWindowSize(int foo){ this.rwsize=foo; } 350 synchronized void addRemoteWindowSize(int foo){ this.rwsize+=foo; } 351 void setRemotePacketSize(int foo){ this.rmpsize=foo; } 352 353 public void run(){ 354 } 355 356 void write(byte[] foo) throws IOException { 357 write(foo, 0, foo.length); 358 } 359 void write(byte[] foo, int s, int l) throws IOException { 360 try{ 361 io.put(foo, s, l); 363 }catch(NullPointerException e){} 364 } 365 void write_ext(byte[] foo, int s, int l) throws IOException { 366 try{ 367 io.put_ext(foo, s, l); 369 }catch(NullPointerException e){} 370 } 371 372 void eof_remote(){ 373 eof_remote=true; 374 try{ 375 if(io.out!=null){ 376 io.out.close(); 377 io.out=null; 378 } 379 } 380 catch(NullPointerException e){} 381 catch(IOException e){} 382 } 383 384 void eof(){ 385 if(close)return; 388 if(eof_local)return; 389 eof_local=true; 390 try{ 392 Buffer buf=new Buffer(100); 393 Packet packet=new Packet(buf); 394 packet.reset(); 395 buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF); 396 buf.putInt(getRecipient()); 397 session.write(packet); 398 } 399 catch(Exception e){ 400 } 403 406 } 407 408 443 444 void close(){ 445 if(close)return; 447 close=true; 448 449 eof_local=eof_remote=true; 450 451 try{ 452 Buffer buf=new Buffer(100); 453 Packet packet=new Packet(buf); 454 packet.reset(); 455 buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE); 456 buf.putInt(getRecipient()); 457 session.write(packet); 458 } 459 catch(Exception e){ 460 } 462 } 463 public boolean isClosed(){ 464 return close; 465 } 466 static void disconnect(Session session){ 467 Channel[] channels=null; 468 int count=0; 469 synchronized(pool){ 470 channels=new Channel[pool.size()]; 471 for(int i=0; i<pool.size(); i++){ 472 try{ 473 Channel c=((Channel)(pool.elementAt(i))); 474 if(c.session==session){ 475 channels[count++]=c; 476 } 477 } 478 catch(Exception e){ 479 } 480 } 481 } 482 for(int i=0; i<count; i++){ 483 channels[i].disconnect(); 484 } 485 } 486 487 public void disconnect(){ 488 491 synchronized(this){ 492 if(!connected){ 493 return; 494 } 495 connected=false; 496 } 497 498 close(); 499 500 eof_remote=eof_local=true; 501 502 thread=null; 503 504 try{ 505 if(io!=null){ 506 io.close(); 507 } 508 } 509 catch(Exception e){ 510 } 512 io=null; 513 Channel.del(this); 514 } 515 516 public boolean isConnected(){ 517 if(this.session!=null){ 518 return session.isConnected() && connected; 519 } 520 return false; 521 } 522 523 public void sendSignal(String foo) throws Exception { 524 RequestSignal request=new RequestSignal(); 525 request.setSignal(foo); 526 request.request(session, this); 527 } 528 529 533 540 541 class PassiveInputStream extends MyPipedInputStream{ 542 PipedOutputStream out; 543 PassiveInputStream(PipedOutputStream out, int size) throws IOException { 544 super(out, size); 545 this.out=out; 546 } 547 PassiveInputStream(PipedOutputStream out) throws IOException { 548 super(out); 549 this.out=out; 550 } 551 public void close() throws IOException { 552 if(out!=null){ 553 this.out.close(); 554 } 555 out=null; 556 } 557 } 558 class PassiveOutputStream extends PipedOutputStream { 559 PassiveOutputStream(PipedInputStream in) throws IOException { 560 super(in); 561 } 562 } 563 564 void setExitStatus(int foo){ exitstatus=foo; } 565 public int getExitStatus(){ return exitstatus; } 566 567 void setSession(Session session){ 568 this.session=session; 569 } 570 public Session getSession(){ return session; } 571 public int getId(){ return id; } 572 574 protected void sendOpenConfirmation() throws Exception { 575 Buffer buf=new Buffer(100); 576 Packet packet=new Packet(buf); 577 packet.reset(); 578 buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_CONFIRMATION); 579 buf.putInt(getRecipient()); 580 buf.putInt(id); 581 buf.putInt(lwsize); 582 buf.putInt(lmpsize); 583 session.write(packet); 584 } 585 586 protected void sendOpenFailure(int reasoncode){ 587 try{ 588 Buffer buf=new Buffer(100); 589 Packet packet=new Packet(buf); 590 packet.reset(); 591 buf.putByte((byte)SSH_MSG_CHANNEL_OPEN_FAILURE); 592 buf.putInt(getRecipient()); 593 buf.putInt(reasoncode); 594 buf.putString("open failed".getBytes()); 595 buf.putString("".getBytes()); 596 session.write(packet); 597 } 598 catch(Exception e){ 599 } 600 } 601 } 602 | Popular Tags |