Source Code Cross Referenced for ChannelManager.java in  » Net » Ganymed-SSH-2 » ch » ethz » ssh2 » channel » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » Ganymed SSH 2 » ch.ethz.ssh2.channel 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package ch.ethz.ssh2.channel;
0002:
0003:        import java.io.IOException;
0004:        import java.util.HashMap;
0005:        import java.util.Vector;
0006:
0007:        import ch.ethz.ssh2.ChannelCondition;
0008:        import ch.ethz.ssh2.log.Logger;
0009:        import ch.ethz.ssh2.packets.PacketChannelOpenConfirmation;
0010:        import ch.ethz.ssh2.packets.PacketChannelOpenFailure;
0011:        import ch.ethz.ssh2.packets.PacketGlobalCancelForwardRequest;
0012:        import ch.ethz.ssh2.packets.PacketGlobalForwardRequest;
0013:        import ch.ethz.ssh2.packets.PacketOpenDirectTCPIPChannel;
0014:        import ch.ethz.ssh2.packets.PacketOpenSessionChannel;
0015:        import ch.ethz.ssh2.packets.PacketSessionExecCommand;
0016:        import ch.ethz.ssh2.packets.PacketSessionPtyRequest;
0017:        import ch.ethz.ssh2.packets.PacketSessionStartShell;
0018:        import ch.ethz.ssh2.packets.PacketSessionSubsystemRequest;
0019:        import ch.ethz.ssh2.packets.PacketSessionX11Request;
0020:        import ch.ethz.ssh2.packets.Packets;
0021:        import ch.ethz.ssh2.packets.TypesReader;
0022:        import ch.ethz.ssh2.transport.MessageHandler;
0023:        import ch.ethz.ssh2.transport.TransportManager;
0024:
0025:        /**
0026:         * ChannelManager. Please read the comments in Channel.java.
0027:         * <p>
0028:         * Besides the crypto part, this is the core of the library.
0029:         * 
0030:         * @author Christian Plattner, plattner@inf.ethz.ch
0031:         * @version $Id: ChannelManager.java,v 1.15 2006/08/11 12:24:01 cplattne Exp $
0032:         */
0033:        public class ChannelManager implements  MessageHandler {
0034:            private static final Logger log = Logger
0035:                    .getLogger(ChannelManager.class);
0036:
0037:            private HashMap x11_magic_cookies = new HashMap();
0038:
0039:            private TransportManager tm;
0040:
0041:            private Vector channels = new Vector();
0042:            private int nextLocalChannel = 100;
0043:            private boolean shutdown = false;
0044:            private int globalSuccessCounter = 0;
0045:            private int globalFailedCounter = 0;
0046:
0047:            private HashMap remoteForwardings = new HashMap();
0048:
0049:            private Vector listenerThreads = new Vector();
0050:
0051:            private boolean listenerThreadsAllowed = true;
0052:
0053:            public ChannelManager(TransportManager tm) {
0054:                this .tm = tm;
0055:                tm.registerMessageHandler(this , 80, 100);
0056:            }
0057:
0058:            private Channel getChannel(int id) {
0059:                synchronized (channels) {
0060:                    for (int i = 0; i < channels.size(); i++) {
0061:                        Channel c = (Channel) channels.elementAt(i);
0062:                        if (c.localID == id)
0063:                            return c;
0064:                    }
0065:                }
0066:                return null;
0067:            }
0068:
0069:            private void removeChannel(int id) {
0070:                synchronized (channels) {
0071:                    for (int i = 0; i < channels.size(); i++) {
0072:                        Channel c = (Channel) channels.elementAt(i);
0073:                        if (c.localID == id) {
0074:                            channels.removeElementAt(i);
0075:                            break;
0076:                        }
0077:                    }
0078:                }
0079:            }
0080:
0081:            private int addChannel(Channel c) {
0082:                synchronized (channels) {
0083:                    channels.addElement(c);
0084:                    return nextLocalChannel++;
0085:                }
0086:            }
0087:
0088:            private void waitUntilChannelOpen(Channel c) throws IOException {
0089:                synchronized (c) {
0090:                    while (c.state == Channel.STATE_OPENING) {
0091:                        try {
0092:                            c.wait();
0093:                        } catch (InterruptedException ignore) {
0094:                        }
0095:                    }
0096:
0097:                    if (c.state != Channel.STATE_OPEN) {
0098:                        removeChannel(c.localID);
0099:
0100:                        String detail = c.getReasonClosed();
0101:
0102:                        if (detail == null)
0103:                            detail = "state: " + c.state;
0104:
0105:                        throw new IOException("Could not open channel ("
0106:                                + detail + ")");
0107:                    }
0108:                }
0109:            }
0110:
0111:            private final void waitForGlobalSuccessOrFailure()
0112:                    throws IOException {
0113:                synchronized (channels) {
0114:                    while ((globalSuccessCounter == 0)
0115:                            && (globalFailedCounter == 0)) {
0116:                        if (shutdown) {
0117:                            throw new IOException(
0118:                                    "The connection is being shutdown");
0119:                        }
0120:
0121:                        try {
0122:                            channels.wait();
0123:                        } catch (InterruptedException ignore) {
0124:                        }
0125:                    }
0126:
0127:                    if (globalFailedCounter != 0) {
0128:                        throw new IOException(
0129:                                "The server denied the request (did you enable port forwarding?)");
0130:                    }
0131:
0132:                    if (globalSuccessCounter == 0) {
0133:                        throw new IOException("Illegal state.");
0134:                    }
0135:
0136:                }
0137:            }
0138:
0139:            private final void waitForChannelSuccessOrFailure(Channel c)
0140:                    throws IOException {
0141:                synchronized (c) {
0142:                    while ((c.successCounter == 0) && (c.failedCounter == 0)) {
0143:                        if (c.state != Channel.STATE_OPEN) {
0144:                            String detail = c.getReasonClosed();
0145:
0146:                            if (detail == null)
0147:                                detail = "state: " + c.state;
0148:
0149:                            throw new IOException(
0150:                                    "This SSH2 channel is not open (" + detail
0151:                                            + ")");
0152:                        }
0153:
0154:                        try {
0155:                            c.wait();
0156:                        } catch (InterruptedException ignore) {
0157:                        }
0158:                    }
0159:
0160:                    if (c.failedCounter != 0) {
0161:                        throw new IOException("The server denied the request.");
0162:                    }
0163:                }
0164:            }
0165:
0166:            public void registerX11Cookie(String hexFakeCookie,
0167:                    X11ServerData data) {
0168:                synchronized (x11_magic_cookies) {
0169:                    x11_magic_cookies.put(hexFakeCookie, data);
0170:                }
0171:            }
0172:
0173:            public void unRegisterX11Cookie(String hexFakeCookie,
0174:                    boolean killChannels) {
0175:                if (hexFakeCookie == null)
0176:                    throw new IllegalStateException(
0177:                            "hexFakeCookie may not be null");
0178:
0179:                synchronized (x11_magic_cookies) {
0180:                    x11_magic_cookies.remove(hexFakeCookie);
0181:                }
0182:
0183:                if (killChannels == false)
0184:                    return;
0185:
0186:                if (log.isEnabled())
0187:                    log
0188:                            .log(50,
0189:                                    "Closing all X11 channels for the given fake cookie");
0190:
0191:                Vector channel_copy;
0192:
0193:                synchronized (channels) {
0194:                    channel_copy = (Vector) channels.clone();
0195:                }
0196:
0197:                for (int i = 0; i < channel_copy.size(); i++) {
0198:                    Channel c = (Channel) channel_copy.elementAt(i);
0199:
0200:                    synchronized (c) {
0201:                        if (hexFakeCookie.equals(c.hexX11FakeCookie) == false)
0202:                            continue;
0203:                    }
0204:
0205:                    try {
0206:                        closeChannel(
0207:                                c,
0208:                                "Closing X11 channel since the corresponding session is closing",
0209:                                true);
0210:                    } catch (IOException e) {
0211:                    }
0212:                }
0213:            }
0214:
0215:            public X11ServerData checkX11Cookie(String hexFakeCookie) {
0216:                synchronized (x11_magic_cookies) {
0217:                    if (hexFakeCookie != null)
0218:                        return (X11ServerData) x11_magic_cookies
0219:                                .get(hexFakeCookie);
0220:                }
0221:                return null;
0222:            }
0223:
0224:            public void closeAllChannels() {
0225:                if (log.isEnabled())
0226:                    log.log(50, "Closing all channels");
0227:
0228:                Vector channel_copy;
0229:
0230:                synchronized (channels) {
0231:                    channel_copy = (Vector) channels.clone();
0232:                }
0233:
0234:                for (int i = 0; i < channel_copy.size(); i++) {
0235:                    Channel c = (Channel) channel_copy.elementAt(i);
0236:                    try {
0237:                        closeChannel(c, "Closing all channels", true);
0238:                    } catch (IOException e) {
0239:                    }
0240:                }
0241:            }
0242:
0243:            public void closeChannel(Channel c, String reason, boolean force)
0244:                    throws IOException {
0245:                byte msg[] = new byte[5];
0246:
0247:                synchronized (c) {
0248:                    if (force) {
0249:                        c.state = Channel.STATE_CLOSED;
0250:                        c.EOF = true;
0251:                    }
0252:
0253:                    c.setReasonClosed(reason);
0254:
0255:                    msg[0] = Packets.SSH_MSG_CHANNEL_CLOSE;
0256:                    msg[1] = (byte) (c.remoteID >> 24);
0257:                    msg[2] = (byte) (c.remoteID >> 16);
0258:                    msg[3] = (byte) (c.remoteID >> 8);
0259:                    msg[4] = (byte) (c.remoteID);
0260:
0261:                    c.notifyAll();
0262:                }
0263:
0264:                synchronized (c.channelSendLock) {
0265:                    if (c.closeMessageSent == true)
0266:                        return;
0267:                    tm.sendMessage(msg);
0268:                    c.closeMessageSent = true;
0269:                }
0270:
0271:                if (log.isEnabled())
0272:                    log.log(50, "Sent SSH_MSG_CHANNEL_CLOSE (channel "
0273:                            + c.localID + ")");
0274:            }
0275:
0276:            public void sendEOF(Channel c) throws IOException {
0277:                byte[] msg = new byte[5];
0278:
0279:                synchronized (c) {
0280:                    if (c.state != Channel.STATE_OPEN)
0281:                        return;
0282:
0283:                    msg[0] = Packets.SSH_MSG_CHANNEL_EOF;
0284:                    msg[1] = (byte) (c.remoteID >> 24);
0285:                    msg[2] = (byte) (c.remoteID >> 16);
0286:                    msg[3] = (byte) (c.remoteID >> 8);
0287:                    msg[4] = (byte) (c.remoteID);
0288:                }
0289:
0290:                synchronized (c.channelSendLock) {
0291:                    if (c.closeMessageSent == true)
0292:                        return;
0293:                    tm.sendMessage(msg);
0294:                }
0295:
0296:                if (log.isEnabled())
0297:                    log.log(50, "Sent EOF (Channel " + c.localID + "/"
0298:                            + c.remoteID + ")");
0299:            }
0300:
0301:            public void sendOpenConfirmation(Channel c) throws IOException {
0302:                PacketChannelOpenConfirmation pcoc = null;
0303:
0304:                synchronized (c) {
0305:                    if (c.state != Channel.STATE_OPENING)
0306:                        return;
0307:
0308:                    c.state = Channel.STATE_OPEN;
0309:
0310:                    pcoc = new PacketChannelOpenConfirmation(c.remoteID,
0311:                            c.localID, c.localWindow, c.localMaxPacketSize);
0312:                }
0313:
0314:                synchronized (c.channelSendLock) {
0315:                    if (c.closeMessageSent == true)
0316:                        return;
0317:                    tm.sendMessage(pcoc.getPayload());
0318:                }
0319:            }
0320:
0321:            public void sendData(Channel c, byte[] buffer, int pos, int len)
0322:                    throws IOException {
0323:                while (len > 0) {
0324:                    int this len = 0;
0325:                    byte[] msg;
0326:
0327:                    synchronized (c) {
0328:                        while (true) {
0329:                            if (c.state == Channel.STATE_CLOSED)
0330:                                throw new IOException(
0331:                                        "SSH channel is closed. ("
0332:                                                + c.getReasonClosed() + ")");
0333:
0334:                            if (c.state != Channel.STATE_OPEN)
0335:                                throw new IOException(
0336:                                        "SSH channel in strange state. ("
0337:                                                + c.state + ")");
0338:
0339:                            if (c.remoteWindow != 0)
0340:                                break;
0341:
0342:                            try {
0343:                                c.wait();
0344:                            } catch (InterruptedException ignore) {
0345:                            }
0346:                        }
0347:
0348:                        /* len > 0, no sign extension can happen when comparing */
0349:
0350:                        this len = (c.remoteWindow >= len) ? len
0351:                                : (int) c.remoteWindow;
0352:
0353:                        int estimatedMaxDataLen = c.remoteMaxPacketSize
0354:                                - (tm.getPacketOverheadEstimate() + 9);
0355:
0356:                        /* The worst case scenario =) a true bottleneck */
0357:
0358:                        if (estimatedMaxDataLen <= 0) {
0359:                            estimatedMaxDataLen = 1;
0360:                        }
0361:
0362:                        if (this len > estimatedMaxDataLen)
0363:                            this len = estimatedMaxDataLen;
0364:
0365:                        c.remoteWindow -= this len;
0366:
0367:                        msg = new byte[1 + 8 + this len];
0368:
0369:                        msg[0] = Packets.SSH_MSG_CHANNEL_DATA;
0370:                        msg[1] = (byte) (c.remoteID >> 24);
0371:                        msg[2] = (byte) (c.remoteID >> 16);
0372:                        msg[3] = (byte) (c.remoteID >> 8);
0373:                        msg[4] = (byte) (c.remoteID);
0374:                        msg[5] = (byte) (this len >> 24);
0375:                        msg[6] = (byte) (this len >> 16);
0376:                        msg[7] = (byte) (this len >> 8);
0377:                        msg[8] = (byte) (this len);
0378:
0379:                        System.arraycopy(buffer, pos, msg, 9, this len);
0380:                    }
0381:
0382:                    synchronized (c.channelSendLock) {
0383:                        if (c.closeMessageSent == true)
0384:                            throw new IOException("SSH channel is closed. ("
0385:                                    + c.getReasonClosed() + ")");
0386:
0387:                        tm.sendMessage(msg);
0388:                    }
0389:
0390:                    pos += this len;
0391:                    len -= this len;
0392:                }
0393:            }
0394:
0395:            public int requestGlobalForward(String bindAddress, int bindPort,
0396:                    String targetAddress, int targetPort) throws IOException {
0397:                RemoteForwardingData rfd = new RemoteForwardingData();
0398:
0399:                rfd.bindAddress = bindAddress;
0400:                rfd.bindPort = bindPort;
0401:                rfd.targetAddress = targetAddress;
0402:                rfd.targetPort = targetPort;
0403:
0404:                synchronized (remoteForwardings) {
0405:                    Integer key = new Integer(bindPort);
0406:
0407:                    if (remoteForwardings.get(key) != null) {
0408:                        throw new IOException(
0409:                                "There is already a forwarding for remote port "
0410:                                        + bindPort);
0411:                    }
0412:
0413:                    remoteForwardings.put(key, rfd);
0414:                }
0415:
0416:                synchronized (channels) {
0417:                    globalSuccessCounter = globalFailedCounter = 0;
0418:                }
0419:
0420:                PacketGlobalForwardRequest pgf = new PacketGlobalForwardRequest(
0421:                        true, bindAddress, bindPort);
0422:                tm.sendMessage(pgf.getPayload());
0423:
0424:                if (log.isEnabled())
0425:                    log.log(50, "Requesting a remote forwarding ('"
0426:                            + bindAddress + "', " + bindPort + ")");
0427:
0428:                try {
0429:                    waitForGlobalSuccessOrFailure();
0430:                } catch (IOException e) {
0431:                    synchronized (remoteForwardings) {
0432:                        remoteForwardings.remove(rfd);
0433:                    }
0434:                    throw e;
0435:                }
0436:
0437:                return bindPort;
0438:            }
0439:
0440:            public void requestCancelGlobalForward(int bindPort)
0441:                    throws IOException {
0442:                RemoteForwardingData rfd = null;
0443:
0444:                synchronized (remoteForwardings) {
0445:                    rfd = (RemoteForwardingData) remoteForwardings
0446:                            .get(new Integer(bindPort));
0447:
0448:                    if (rfd == null)
0449:                        throw new IOException(
0450:                                "Sorry, there is no known remote forwarding for remote port "
0451:                                        + bindPort);
0452:                }
0453:
0454:                synchronized (channels) {
0455:                    globalSuccessCounter = globalFailedCounter = 0;
0456:                }
0457:
0458:                PacketGlobalCancelForwardRequest pgcf = new PacketGlobalCancelForwardRequest(
0459:                        true, rfd.bindAddress, rfd.bindPort);
0460:                tm.sendMessage(pgcf.getPayload());
0461:
0462:                if (log.isEnabled())
0463:                    log.log(50, "Requesting cancelation of remote forward ('"
0464:                            + rfd.bindAddress + "', " + rfd.bindPort + ")");
0465:
0466:                waitForGlobalSuccessOrFailure();
0467:
0468:                /* Only now we are sure that no more forwarded connections will arrive */
0469:
0470:                synchronized (remoteForwardings) {
0471:                    remoteForwardings.remove(rfd);
0472:                }
0473:            }
0474:
0475:            public void registerThread(IChannelWorkerThread thr)
0476:                    throws IOException {
0477:                synchronized (listenerThreads) {
0478:                    if (listenerThreadsAllowed == false)
0479:                        throw new IOException(
0480:                                "Too late, this connection is closed.");
0481:                    listenerThreads.addElement(thr);
0482:                }
0483:            }
0484:
0485:            public Channel openDirectTCPIPChannel(String host_to_connect,
0486:                    int port_to_connect, String originator_IP_address,
0487:                    int originator_port) throws IOException {
0488:                Channel c = new Channel(this );
0489:
0490:                synchronized (c) {
0491:                    c.localID = addChannel(c);
0492:                    // end of synchronized block forces writing out to main memory
0493:                }
0494:
0495:                PacketOpenDirectTCPIPChannel dtc = new PacketOpenDirectTCPIPChannel(
0496:                        c.localID, c.localWindow, c.localMaxPacketSize,
0497:                        host_to_connect, port_to_connect,
0498:                        originator_IP_address, originator_port);
0499:
0500:                tm.sendMessage(dtc.getPayload());
0501:
0502:                waitUntilChannelOpen(c);
0503:
0504:                return c;
0505:            }
0506:
0507:            public Channel openSessionChannel() throws IOException {
0508:                Channel c = new Channel(this );
0509:
0510:                synchronized (c) {
0511:                    c.localID = addChannel(c);
0512:                    // end of synchronized block forces the writing out to main memory
0513:                }
0514:
0515:                if (log.isEnabled())
0516:                    log.log(50, "Sending SSH_MSG_CHANNEL_OPEN (Channel "
0517:                            + c.localID + ")");
0518:
0519:                PacketOpenSessionChannel smo = new PacketOpenSessionChannel(
0520:                        c.localID, c.localWindow, c.localMaxPacketSize);
0521:                tm.sendMessage(smo.getPayload());
0522:
0523:                waitUntilChannelOpen(c);
0524:
0525:                return c;
0526:            }
0527:
0528:            public void requestPTY(Channel c, String term,
0529:                    int term_width_characters, int term_height_characters,
0530:                    int term_width_pixels, int term_height_pixels,
0531:                    byte[] terminal_modes) throws IOException {
0532:                PacketSessionPtyRequest spr;
0533:
0534:                synchronized (c) {
0535:                    if (c.state != Channel.STATE_OPEN)
0536:                        throw new IOException(
0537:                                "Cannot request PTY on this channel ("
0538:                                        + c.getReasonClosed() + ")");
0539:
0540:                    spr = new PacketSessionPtyRequest(c.remoteID, true, term,
0541:                            term_width_characters, term_height_characters,
0542:                            term_width_pixels, term_height_pixels,
0543:                            terminal_modes);
0544:
0545:                    c.successCounter = c.failedCounter = 0;
0546:                }
0547:
0548:                synchronized (c.channelSendLock) {
0549:                    if (c.closeMessageSent)
0550:                        throw new IOException(
0551:                                "Cannot request PTY on this channel ("
0552:                                        + c.getReasonClosed() + ")");
0553:                    tm.sendMessage(spr.getPayload());
0554:                }
0555:
0556:                try {
0557:                    waitForChannelSuccessOrFailure(c);
0558:                } catch (IOException e) {
0559:                    throw (IOException) new IOException("PTY request failed")
0560:                            .initCause(e);
0561:                }
0562:            }
0563:
0564:            public void requestX11(Channel c, boolean singleConnection,
0565:                    String x11AuthenticationProtocol,
0566:                    String x11AuthenticationCookie, int x11ScreenNumber)
0567:                    throws IOException {
0568:                PacketSessionX11Request psr;
0569:
0570:                synchronized (c) {
0571:                    if (c.state != Channel.STATE_OPEN)
0572:                        throw new IOException(
0573:                                "Cannot request X11 on this channel ("
0574:                                        + c.getReasonClosed() + ")");
0575:
0576:                    psr = new PacketSessionX11Request(c.remoteID, true,
0577:                            singleConnection, x11AuthenticationProtocol,
0578:                            x11AuthenticationCookie, x11ScreenNumber);
0579:
0580:                    c.successCounter = c.failedCounter = 0;
0581:                }
0582:
0583:                synchronized (c.channelSendLock) {
0584:                    if (c.closeMessageSent)
0585:                        throw new IOException(
0586:                                "Cannot request X11 on this channel ("
0587:                                        + c.getReasonClosed() + ")");
0588:                    tm.sendMessage(psr.getPayload());
0589:                }
0590:
0591:                if (log.isEnabled())
0592:                    log.log(50, "Requesting X11 forwarding (Channel "
0593:                            + c.localID + "/" + c.remoteID + ")");
0594:
0595:                try {
0596:                    waitForChannelSuccessOrFailure(c);
0597:                } catch (IOException e) {
0598:                    throw (IOException) new IOException(
0599:                            "The X11 request failed.").initCause(e);
0600:                }
0601:            }
0602:
0603:            public void requestSubSystem(Channel c, String subSystemName)
0604:                    throws IOException {
0605:                PacketSessionSubsystemRequest ssr;
0606:
0607:                synchronized (c) {
0608:                    if (c.state != Channel.STATE_OPEN)
0609:                        throw new IOException(
0610:                                "Cannot request subsystem on this channel ("
0611:                                        + c.getReasonClosed() + ")");
0612:
0613:                    ssr = new PacketSessionSubsystemRequest(c.remoteID, true,
0614:                            subSystemName);
0615:
0616:                    c.successCounter = c.failedCounter = 0;
0617:                }
0618:
0619:                synchronized (c.channelSendLock) {
0620:                    if (c.closeMessageSent)
0621:                        throw new IOException(
0622:                                "Cannot request subsystem on this channel ("
0623:                                        + c.getReasonClosed() + ")");
0624:                    tm.sendMessage(ssr.getPayload());
0625:                }
0626:
0627:                try {
0628:                    waitForChannelSuccessOrFailure(c);
0629:                } catch (IOException e) {
0630:                    throw (IOException) new IOException(
0631:                            "The subsystem request failed.").initCause(e);
0632:                }
0633:            }
0634:
0635:            public void requestExecCommand(Channel c, String cmd)
0636:                    throws IOException {
0637:                PacketSessionExecCommand sm;
0638:
0639:                synchronized (c) {
0640:                    if (c.state != Channel.STATE_OPEN)
0641:                        throw new IOException(
0642:                                "Cannot execute command on this channel ("
0643:                                        + c.getReasonClosed() + ")");
0644:
0645:                    sm = new PacketSessionExecCommand(c.remoteID, true, cmd);
0646:
0647:                    c.successCounter = c.failedCounter = 0;
0648:                }
0649:
0650:                synchronized (c.channelSendLock) {
0651:                    if (c.closeMessageSent)
0652:                        throw new IOException(
0653:                                "Cannot execute command on this channel ("
0654:                                        + c.getReasonClosed() + ")");
0655:                    tm.sendMessage(sm.getPayload());
0656:                }
0657:
0658:                if (log.isEnabled())
0659:                    log.log(50, "Executing command (channel " + c.localID
0660:                            + ", '" + cmd + "')");
0661:
0662:                try {
0663:                    waitForChannelSuccessOrFailure(c);
0664:                } catch (IOException e) {
0665:                    throw (IOException) new IOException(
0666:                            "The execute request failed.").initCause(e);
0667:                }
0668:            }
0669:
0670:            public void requestShell(Channel c) throws IOException {
0671:                PacketSessionStartShell sm;
0672:
0673:                synchronized (c) {
0674:                    if (c.state != Channel.STATE_OPEN)
0675:                        throw new IOException(
0676:                                "Cannot start shell on this channel ("
0677:                                        + c.getReasonClosed() + ")");
0678:
0679:                    sm = new PacketSessionStartShell(c.remoteID, true);
0680:
0681:                    c.successCounter = c.failedCounter = 0;
0682:                }
0683:
0684:                synchronized (c.channelSendLock) {
0685:                    if (c.closeMessageSent)
0686:                        throw new IOException(
0687:                                "Cannot start shell on this channel ("
0688:                                        + c.getReasonClosed() + ")");
0689:                    tm.sendMessage(sm.getPayload());
0690:                }
0691:
0692:                try {
0693:                    waitForChannelSuccessOrFailure(c);
0694:                } catch (IOException e) {
0695:                    throw (IOException) new IOException(
0696:                            "The shell request failed.").initCause(e);
0697:                }
0698:            }
0699:
0700:            public void msgChannelExtendedData(byte[] msg, int msglen)
0701:                    throws IOException {
0702:                if (msglen <= 13)
0703:                    throw new IOException(
0704:                            "SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong size ("
0705:                                    + msglen + ")");
0706:
0707:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
0708:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
0709:                int dataType = ((msg[5] & 0xff) << 24)
0710:                        | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8)
0711:                        | (msg[8] & 0xff);
0712:                int len = ((msg[9] & 0xff) << 24) | ((msg[10] & 0xff) << 16)
0713:                        | ((msg[11] & 0xff) << 8) | (msg[12] & 0xff);
0714:
0715:                Channel c = getChannel(id);
0716:
0717:                if (c == null)
0718:                    throw new IOException(
0719:                            "Unexpected SSH_MSG_CHANNEL_EXTENDED_DATA message for non-existent channel "
0720:                                    + id);
0721:
0722:                if (dataType != Packets.SSH_EXTENDED_DATA_STDERR)
0723:                    throw new IOException(
0724:                            "SSH_MSG_CHANNEL_EXTENDED_DATA message has unknown type ("
0725:                                    + dataType + ")");
0726:
0727:                if (len != (msglen - 13))
0728:                    throw new IOException(
0729:                            "SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong len (calculated "
0730:                                    + (msglen - 13) + ", got " + len + ")");
0731:
0732:                if (log.isEnabled())
0733:                    log.log(80, "Got SSH_MSG_CHANNEL_EXTENDED_DATA (channel "
0734:                            + id + ", " + len + ")");
0735:
0736:                synchronized (c) {
0737:                    if (c.state == Channel.STATE_CLOSED)
0738:                        return; // ignore
0739:
0740:                    if (c.state != Channel.STATE_OPEN)
0741:                        throw new IOException(
0742:                                "Got SSH_MSG_CHANNEL_EXTENDED_DATA, but channel is not in correct state ("
0743:                                        + c.state + ")");
0744:
0745:                    if (c.localWindow < len)
0746:                        throw new IOException(
0747:                                "Remote sent too much data, does not fit into window.");
0748:
0749:                    c.localWindow -= len;
0750:
0751:                    System.arraycopy(msg, 13, c.stderrBuffer, c.stderrWritepos,
0752:                            len);
0753:                    c.stderrWritepos += len;
0754:
0755:                    c.notifyAll();
0756:                }
0757:            }
0758:
0759:            /**
0760:             * Wait until for a condition.
0761:             * 
0762:             * @param c
0763:             *            Channel
0764:             * @param timeout
0765:             *            in ms, 0 means no timeout.
0766:             * @param condition_mask
0767:             *            minimum event mask
0768:             * @return all current events
0769:             * 
0770:             */
0771:            public int waitForCondition(Channel c, long timeout,
0772:                    int condition_mask) {
0773:                long end_time = 0;
0774:                boolean end_time_set = false;
0775:
0776:                synchronized (c) {
0777:                    while (true) {
0778:                        int current_cond = 0;
0779:
0780:                        int stdoutAvail = c.stdoutWritepos - c.stdoutReadpos;
0781:                        int stderrAvail = c.stderrWritepos - c.stderrReadpos;
0782:
0783:                        if (stdoutAvail > 0)
0784:                            current_cond = current_cond
0785:                                    | ChannelCondition.STDOUT_DATA;
0786:
0787:                        if (stderrAvail > 0)
0788:                            current_cond = current_cond
0789:                                    | ChannelCondition.STDERR_DATA;
0790:
0791:                        if (c.EOF)
0792:                            current_cond = current_cond | ChannelCondition.EOF;
0793:
0794:                        if (c.getExitStatus() != null)
0795:                            current_cond = current_cond
0796:                                    | ChannelCondition.EXIT_STATUS;
0797:
0798:                        if (c.getExitSignal() != null)
0799:                            current_cond = current_cond
0800:                                    | ChannelCondition.EXIT_SIGNAL;
0801:
0802:                        if (c.state == Channel.STATE_CLOSED)
0803:                            return current_cond | ChannelCondition.CLOSED
0804:                                    | ChannelCondition.EOF;
0805:
0806:                        if ((current_cond & condition_mask) != 0)
0807:                            return current_cond;
0808:
0809:                        if (timeout > 0) {
0810:                            if (!end_time_set) {
0811:                                end_time = System.currentTimeMillis() + timeout;
0812:                                end_time_set = true;
0813:                            } else {
0814:                                timeout = end_time - System.currentTimeMillis();
0815:
0816:                                if (timeout <= 0)
0817:                                    return current_cond
0818:                                            | ChannelCondition.TIMEOUT;
0819:                            }
0820:                        }
0821:
0822:                        try {
0823:                            if (timeout > 0)
0824:                                c.wait(timeout);
0825:                            else
0826:                                c.wait();
0827:                        } catch (InterruptedException e) {
0828:                        }
0829:                    }
0830:                }
0831:            }
0832:
0833:            public int getAvailable(Channel c, boolean extended)
0834:                    throws IOException {
0835:                synchronized (c) {
0836:                    int avail;
0837:
0838:                    if (extended)
0839:                        avail = c.stderrWritepos - c.stderrReadpos;
0840:                    else
0841:                        avail = c.stdoutWritepos - c.stdoutReadpos;
0842:
0843:                    return ((avail > 0) ? avail : (c.EOF ? -1 : 0));
0844:                }
0845:            }
0846:
0847:            public int getChannelData(Channel c, boolean extended,
0848:                    byte[] target, int off, int len) throws IOException {
0849:                int copylen = 0;
0850:                int increment = 0;
0851:                int remoteID = 0;
0852:                int localID = 0;
0853:
0854:                synchronized (c) {
0855:                    int stdoutAvail = 0;
0856:                    int stderrAvail = 0;
0857:
0858:                    while (true) {
0859:                        /*
0860:                         * Data available? We have to return remaining data even if the
0861:                         * channel is already closed.
0862:                         */
0863:
0864:                        stdoutAvail = c.stdoutWritepos - c.stdoutReadpos;
0865:                        stderrAvail = c.stderrWritepos - c.stderrReadpos;
0866:
0867:                        if ((!extended) && (stdoutAvail != 0))
0868:                            break;
0869:
0870:                        if ((extended) && (stderrAvail != 0))
0871:                            break;
0872:
0873:                        /* Do not wait if more data will never arrive (EOF or CLOSED) */
0874:
0875:                        if ((c.EOF) || (c.state != Channel.STATE_OPEN))
0876:                            return -1;
0877:
0878:                        try {
0879:                            c.wait();
0880:                        } catch (InterruptedException ignore) {
0881:                        }
0882:                    }
0883:
0884:                    /* OK, there is some data. Return it. */
0885:
0886:                    if (!extended) {
0887:                        copylen = (stdoutAvail > len) ? len : stdoutAvail;
0888:                        System.arraycopy(c.stdoutBuffer, c.stdoutReadpos,
0889:                                target, off, copylen);
0890:                        c.stdoutReadpos += copylen;
0891:
0892:                        if (c.stdoutReadpos != c.stdoutWritepos)
0893:
0894:                            System.arraycopy(c.stdoutBuffer, c.stdoutReadpos,
0895:                                    c.stdoutBuffer, 0, c.stdoutWritepos
0896:                                            - c.stdoutReadpos);
0897:
0898:                        c.stdoutWritepos -= c.stdoutReadpos;
0899:                        c.stdoutReadpos = 0;
0900:                    } else {
0901:                        copylen = (stderrAvail > len) ? len : stderrAvail;
0902:                        System.arraycopy(c.stderrBuffer, c.stderrReadpos,
0903:                                target, off, copylen);
0904:                        c.stderrReadpos += copylen;
0905:
0906:                        if (c.stderrReadpos != c.stderrWritepos)
0907:
0908:                            System.arraycopy(c.stderrBuffer, c.stderrReadpos,
0909:                                    c.stderrBuffer, 0, c.stderrWritepos
0910:                                            - c.stderrReadpos);
0911:
0912:                        c.stderrWritepos -= c.stderrReadpos;
0913:                        c.stderrReadpos = 0;
0914:                    }
0915:
0916:                    if (c.state != Channel.STATE_OPEN)
0917:                        return copylen;
0918:
0919:                    if (c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) {
0920:                        int minFreeSpace = Math.min(Channel.CHANNEL_BUFFER_SIZE
0921:                                - c.stdoutWritepos, Channel.CHANNEL_BUFFER_SIZE
0922:                                - c.stderrWritepos);
0923:
0924:                        increment = minFreeSpace - c.localWindow;
0925:                        c.localWindow = minFreeSpace;
0926:                    }
0927:
0928:                    remoteID = c.remoteID; /* read while holding the lock */
0929:                    localID = c.localID; /* read while holding the lock */
0930:                }
0931:
0932:                /*
0933:                 * If a consumer reads stdout and stdin in parallel, we may end up with
0934:                 * sending two msgWindowAdjust messages. Luckily, it
0935:                 * does not matter in which order they arrive at the server.
0936:                 */
0937:
0938:                if (increment > 0) {
0939:                    if (log.isEnabled())
0940:                        log.log(80,
0941:                                "Sending SSH_MSG_CHANNEL_WINDOW_ADJUST (channel "
0942:                                        + localID + ", " + increment + ")");
0943:
0944:                    synchronized (c.channelSendLock) {
0945:                        byte[] msg = c.msgWindowAdjust;
0946:
0947:                        msg[0] = Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST;
0948:                        msg[1] = (byte) (remoteID >> 24);
0949:                        msg[2] = (byte) (remoteID >> 16);
0950:                        msg[3] = (byte) (remoteID >> 8);
0951:                        msg[4] = (byte) (remoteID);
0952:                        msg[5] = (byte) (increment >> 24);
0953:                        msg[6] = (byte) (increment >> 16);
0954:                        msg[7] = (byte) (increment >> 8);
0955:                        msg[8] = (byte) (increment);
0956:
0957:                        if (c.closeMessageSent == false)
0958:                            tm.sendMessage(msg);
0959:                    }
0960:                }
0961:
0962:                return copylen;
0963:            }
0964:
0965:            public void msgChannelData(byte[] msg, int msglen)
0966:                    throws IOException {
0967:                if (msglen <= 9)
0968:                    throw new IOException(
0969:                            "SSH_MSG_CHANNEL_DATA message has wrong size ("
0970:                                    + msglen + ")");
0971:
0972:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
0973:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
0974:                int len = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16)
0975:                        | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff);
0976:
0977:                Channel c = getChannel(id);
0978:
0979:                if (c == null)
0980:                    throw new IOException(
0981:                            "Unexpected SSH_MSG_CHANNEL_DATA message for non-existent channel "
0982:                                    + id);
0983:
0984:                if (len != (msglen - 9))
0985:                    throw new IOException(
0986:                            "SSH_MSG_CHANNEL_DATA message has wrong len (calculated "
0987:                                    + (msglen - 9) + ", got " + len + ")");
0988:
0989:                if (log.isEnabled())
0990:                    log.log(80, "Got SSH_MSG_CHANNEL_DATA (channel " + id
0991:                            + ", " + len + ")");
0992:
0993:                synchronized (c) {
0994:                    if (c.state == Channel.STATE_CLOSED)
0995:                        return; // ignore
0996:
0997:                    if (c.state != Channel.STATE_OPEN)
0998:                        throw new IOException(
0999:                                "Got SSH_MSG_CHANNEL_DATA, but channel is not in correct state ("
1000:                                        + c.state + ")");
1001:
1002:                    if (c.localWindow < len)
1003:                        throw new IOException(
1004:                                "Remote sent too much data, does not fit into window.");
1005:
1006:                    c.localWindow -= len;
1007:
1008:                    System.arraycopy(msg, 9, c.stdoutBuffer, c.stdoutWritepos,
1009:                            len);
1010:                    c.stdoutWritepos += len;
1011:
1012:                    c.notifyAll();
1013:                }
1014:            }
1015:
1016:            public void msgChannelWindowAdjust(byte[] msg, int msglen)
1017:                    throws IOException {
1018:                if (msglen != 9)
1019:                    throw new IOException(
1020:                            "SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size ("
1021:                                    + msglen + ")");
1022:
1023:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
1024:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
1025:                int windowChange = ((msg[5] & 0xff) << 24)
1026:                        | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8)
1027:                        | (msg[8] & 0xff);
1028:
1029:                Channel c = getChannel(id);
1030:
1031:                if (c == null)
1032:                    throw new IOException(
1033:                            "Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel "
1034:                                    + id);
1035:
1036:                synchronized (c) {
1037:                    final long huge = 0xFFFFffffL; /* 2^32 - 1 */
1038:
1039:                    c.remoteWindow += (windowChange & huge); /* avoid sign extension */
1040:
1041:                    /* TODO - is this a good heuristic? */
1042:
1043:                    if ((c.remoteWindow > huge))
1044:                        c.remoteWindow = huge;
1045:
1046:                    c.notifyAll();
1047:                }
1048:
1049:                if (log.isEnabled())
1050:                    log.log(80, "Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel "
1051:                            + id + ", " + windowChange + ")");
1052:            }
1053:
1054:            public void msgChannelOpen(byte[] msg, int msglen)
1055:                    throws IOException {
1056:                TypesReader tr = new TypesReader(msg, 0, msglen);
1057:
1058:                tr.readByte(); // skip packet type
1059:                String channelType = tr.readString();
1060:                int remoteID = tr.readUINT32(); /* sender channel */
1061:                int remoteWindow = tr.readUINT32(); /* initial window size */
1062:                int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */
1063:
1064:                if ("x11".equals(channelType)) {
1065:                    synchronized (x11_magic_cookies) {
1066:                        /* If we did not request X11 forwarding, then simply ignore this bogus request. */
1067:
1068:                        if (x11_magic_cookies.size() == 0) {
1069:                            PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(
1070:                                    remoteID,
1071:                                    Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
1072:                                    "X11 forwarding not activated", "");
1073:
1074:                            tm.sendAsynchronousMessage(pcof.getPayload());
1075:
1076:                            if (log.isEnabled())
1077:                                log.log(20,
1078:                                        "Unexpected X11 request, denying it!");
1079:
1080:                            return;
1081:                        }
1082:                    }
1083:
1084:                    String remoteOriginatorAddress = tr.readString();
1085:                    int remoteOriginatorPort = tr.readUINT32();
1086:
1087:                    Channel c = new Channel(this );
1088:
1089:                    synchronized (c) {
1090:                        c.remoteID = remoteID;
1091:                        c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */
1092:                        c.remoteMaxPacketSize = remoteMaxPacketSize;
1093:                        c.localID = addChannel(c);
1094:                    }
1095:
1096:                    /*
1097:                     * The open confirmation message will be sent from another thread
1098:                     */
1099:
1100:                    RemoteX11AcceptThread rxat = new RemoteX11AcceptThread(c,
1101:                            remoteOriginatorAddress, remoteOriginatorPort);
1102:                    rxat.setDaemon(true);
1103:                    rxat.start();
1104:
1105:                    return;
1106:                }
1107:
1108:                if ("forwarded-tcpip".equals(channelType)) {
1109:                    String remoteConnectedAddress = tr.readString(); /* address that was connected */
1110:                    int remoteConnectedPort = tr.readUINT32(); /* port that was connected */
1111:                    String remoteOriginatorAddress = tr.readString(); /* originator IP address */
1112:                    int remoteOriginatorPort = tr.readUINT32(); /* originator port */
1113:
1114:                    RemoteForwardingData rfd = null;
1115:
1116:                    synchronized (remoteForwardings) {
1117:                        rfd = (RemoteForwardingData) remoteForwardings
1118:                                .get(new Integer(remoteConnectedPort));
1119:                    }
1120:
1121:                    if (rfd == null) {
1122:                        PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(
1123:                                remoteID,
1124:                                Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
1125:                                "No thanks, unknown port in forwarded-tcpip request",
1126:                                "");
1127:
1128:                        /* Always try to be polite. */
1129:
1130:                        tm.sendAsynchronousMessage(pcof.getPayload());
1131:
1132:                        if (log.isEnabled())
1133:                            log
1134:                                    .log(20,
1135:                                            "Unexpected forwarded-tcpip request, denying it!");
1136:
1137:                        return;
1138:                    }
1139:
1140:                    Channel c = new Channel(this );
1141:
1142:                    synchronized (c) {
1143:                        c.remoteID = remoteID;
1144:                        c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */
1145:                        c.remoteMaxPacketSize = remoteMaxPacketSize;
1146:                        c.localID = addChannel(c);
1147:                    }
1148:
1149:                    /*
1150:                     * The open confirmation message will be sent from another thread.
1151:                     */
1152:
1153:                    RemoteAcceptThread rat = new RemoteAcceptThread(c,
1154:                            remoteConnectedAddress, remoteConnectedPort,
1155:                            remoteOriginatorAddress, remoteOriginatorPort,
1156:                            rfd.targetAddress, rfd.targetPort);
1157:
1158:                    rat.setDaemon(true);
1159:                    rat.start();
1160:
1161:                    return;
1162:                }
1163:
1164:                /* Tell the server that we have no idea what it is talking about */
1165:
1166:                PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(
1167:                        remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE,
1168:                        "Unknown channel type", "");
1169:
1170:                tm.sendAsynchronousMessage(pcof.getPayload());
1171:
1172:                if (log.isEnabled())
1173:                    log.log(20,
1174:                            "The peer tried to open an unsupported channel type ("
1175:                                    + channelType + ")");
1176:            }
1177:
1178:            public void msgChannelRequest(byte[] msg, int msglen)
1179:                    throws IOException {
1180:                TypesReader tr = new TypesReader(msg, 0, msglen);
1181:
1182:                tr.readByte(); // skip packet type
1183:                int id = tr.readUINT32();
1184:
1185:                Channel c = getChannel(id);
1186:
1187:                if (c == null)
1188:                    throw new IOException(
1189:                            "Unexpected SSH_MSG_CHANNEL_REQUEST message for non-existent channel "
1190:                                    + id);
1191:
1192:                String type = tr.readString("US-ASCII");
1193:                boolean wantReply = tr.readBoolean();
1194:
1195:                if (log.isEnabled())
1196:                    log.log(80, "Got SSH_MSG_CHANNEL_REQUEST (channel " + id
1197:                            + ", '" + type + "')");
1198:
1199:                if (type.equals("exit-status")) {
1200:                    if (wantReply != false)
1201:                        throw new IOException(
1202:                                "Badly formatted SSH_MSG_CHANNEL_REQUEST message, 'want reply' is true");
1203:
1204:                    int exit_status = tr.readUINT32();
1205:
1206:                    if (tr.remain() != 0)
1207:                        throw new IOException(
1208:                                "Badly formatted SSH_MSG_CHANNEL_REQUEST message");
1209:
1210:                    synchronized (c) {
1211:                        c.exit_status = new Integer(exit_status);
1212:                        c.notifyAll();
1213:                    }
1214:
1215:                    if (log.isEnabled())
1216:                        log.log(50, "Got EXIT STATUS (channel " + id
1217:                                + ", status " + exit_status + ")");
1218:
1219:                    return;
1220:                }
1221:
1222:                if (type.equals("exit-signal")) {
1223:                    if (wantReply != false)
1224:                        throw new IOException(
1225:                                "Badly formatted SSH_MSG_CHANNEL_REQUEST message, 'want reply' is true");
1226:
1227:                    String signame = tr.readString("US-ASCII");
1228:                    tr.readBoolean();
1229:                    tr.readString();
1230:                    tr.readString();
1231:
1232:                    if (tr.remain() != 0)
1233:                        throw new IOException(
1234:                                "Badly formatted SSH_MSG_CHANNEL_REQUEST message");
1235:
1236:                    synchronized (c) {
1237:                        c.exit_signal = signame;
1238:                        c.notifyAll();
1239:                    }
1240:
1241:                    if (log.isEnabled())
1242:                        log.log(50, "Got EXIT SIGNAL (channel " + id
1243:                                + ", signal " + signame + ")");
1244:
1245:                    return;
1246:                }
1247:
1248:                /* We simply ignore unknown channel requests, however, if the server wants a reply,
1249:                 * then we signal that we have no idea what it is about.
1250:                 */
1251:
1252:                if (wantReply) {
1253:                    byte[] reply = new byte[5];
1254:
1255:                    reply[0] = Packets.SSH_MSG_CHANNEL_FAILURE;
1256:                    reply[1] = (byte) (c.remoteID >> 24);
1257:                    reply[2] = (byte) (c.remoteID >> 16);
1258:                    reply[3] = (byte) (c.remoteID >> 8);
1259:                    reply[4] = (byte) (c.remoteID);
1260:
1261:                    tm.sendAsynchronousMessage(reply);
1262:                }
1263:
1264:                if (log.isEnabled())
1265:                    log.log(50, "Channel request '" + type
1266:                            + "' is not known, ignoring it");
1267:            }
1268:
1269:            public void msgChannelEOF(byte[] msg, int msglen)
1270:                    throws IOException {
1271:                if (msglen != 5)
1272:                    throw new IOException(
1273:                            "SSH_MSG_CHANNEL_EOF message has wrong size ("
1274:                                    + msglen + ")");
1275:
1276:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
1277:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
1278:
1279:                Channel c = getChannel(id);
1280:
1281:                if (c == null)
1282:                    throw new IOException(
1283:                            "Unexpected SSH_MSG_CHANNEL_EOF message for non-existent channel "
1284:                                    + id);
1285:
1286:                synchronized (c) {
1287:                    c.EOF = true;
1288:                    c.notifyAll();
1289:                }
1290:
1291:                if (log.isEnabled())
1292:                    log.log(50, "Got SSH_MSG_CHANNEL_EOF (channel " + id + ")");
1293:            }
1294:
1295:            public void msgChannelClose(byte[] msg, int msglen)
1296:                    throws IOException {
1297:                if (msglen != 5)
1298:                    throw new IOException(
1299:                            "SSH_MSG_CHANNEL_CLOSE message has wrong size ("
1300:                                    + msglen + ")");
1301:
1302:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
1303:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
1304:
1305:                Channel c = getChannel(id);
1306:
1307:                if (c == null)
1308:                    throw new IOException(
1309:                            "Unexpected SSH_MSG_CHANNEL_CLOSE message for non-existent channel "
1310:                                    + id);
1311:
1312:                synchronized (c) {
1313:                    c.EOF = true;
1314:                    c.state = Channel.STATE_CLOSED;
1315:                    c.setReasonClosed("Close requested by remote");
1316:                    c.closeMessageRecv = true;
1317:
1318:                    removeChannel(c.localID);
1319:
1320:                    c.notifyAll();
1321:                }
1322:
1323:                if (log.isEnabled())
1324:                    log.log(50, "Got SSH_MSG_CHANNEL_CLOSE (channel " + id
1325:                            + ")");
1326:            }
1327:
1328:            public void msgChannelSuccess(byte[] msg, int msglen)
1329:                    throws IOException {
1330:                if (msglen != 5)
1331:                    throw new IOException(
1332:                            "SSH_MSG_CHANNEL_SUCCESS message has wrong size ("
1333:                                    + msglen + ")");
1334:
1335:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
1336:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
1337:
1338:                Channel c = getChannel(id);
1339:
1340:                if (c == null)
1341:                    throw new IOException(
1342:                            "Unexpected SSH_MSG_CHANNEL_SUCCESS message for non-existent channel "
1343:                                    + id);
1344:
1345:                synchronized (c) {
1346:                    c.successCounter++;
1347:                    c.notifyAll();
1348:                }
1349:
1350:                if (log.isEnabled())
1351:                    log.log(80, "Got SSH_MSG_CHANNEL_SUCCESS (channel " + id
1352:                            + ")");
1353:            }
1354:
1355:            public void msgChannelFailure(byte[] msg, int msglen)
1356:                    throws IOException {
1357:                if (msglen != 5)
1358:                    throw new IOException(
1359:                            "SSH_MSG_CHANNEL_FAILURE message has wrong size ("
1360:                                    + msglen + ")");
1361:
1362:                int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16)
1363:                        | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff);
1364:
1365:                Channel c = getChannel(id);
1366:
1367:                if (c == null)
1368:                    throw new IOException(
1369:                            "Unexpected SSH_MSG_CHANNEL_FAILURE message for non-existent channel "
1370:                                    + id);
1371:
1372:                synchronized (c) {
1373:                    c.failedCounter++;
1374:                    c.notifyAll();
1375:                }
1376:
1377:                if (log.isEnabled())
1378:                    log.log(50, "Got SSH_MSG_CHANNEL_FAILURE (channel " + id
1379:                            + ")");
1380:            }
1381:
1382:            public void msgChannelOpenConfirmation(byte[] msg, int msglen)
1383:                    throws IOException {
1384:                PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(
1385:                        msg, 0, msglen);
1386:
1387:                Channel c = getChannel(sm.recipientChannelID);
1388:
1389:                if (c == null)
1390:                    throw new IOException(
1391:                            "Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel "
1392:                                    + sm.recipientChannelID);
1393:
1394:                synchronized (c) {
1395:                    if (c.state != Channel.STATE_OPENING)
1396:                        throw new IOException(
1397:                                "Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel "
1398:                                        + sm.recipientChannelID);
1399:
1400:                    c.remoteID = sm.senderChannelID;
1401:                    c.remoteWindow = sm.initialWindowSize & 0xFFFFffffL; /* convert UINT32 to long */
1402:                    c.remoteMaxPacketSize = sm.maxPacketSize;
1403:                    c.state = Channel.STATE_OPEN;
1404:                    c.notifyAll();
1405:                }
1406:
1407:                if (log.isEnabled())
1408:                    log.log(50,
1409:                            "Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel "
1410:                                    + sm.recipientChannelID + " / remote: "
1411:                                    + sm.senderChannelID + ")");
1412:            }
1413:
1414:            public void msgChannelOpenFailure(byte[] msg, int msglen)
1415:                    throws IOException {
1416:                if (msglen < 5)
1417:                    throw new IOException(
1418:                            "SSH_MSG_CHANNEL_OPEN_FAILURE message has wrong size ("
1419:                                    + msglen + ")");
1420:
1421:                TypesReader tr = new TypesReader(msg, 0, msglen);
1422:
1423:                tr.readByte(); // skip packet type
1424:                int id = tr.readUINT32(); /* sender channel */
1425:
1426:                Channel c = getChannel(id);
1427:
1428:                if (c == null)
1429:                    throw new IOException(
1430:                            "Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE message for non-existent channel "
1431:                                    + id);
1432:
1433:                int reasonCode = tr.readUINT32();
1434:                String description = tr.readString("UTF-8");
1435:
1436:                String reasonCodeSymbolicName = null;
1437:
1438:                switch (reasonCode) {
1439:                case 1:
1440:                    reasonCodeSymbolicName = "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED";
1441:                    break;
1442:                case 2:
1443:                    reasonCodeSymbolicName = "SSH_OPEN_CONNECT_FAILED";
1444:                    break;
1445:                case 3:
1446:                    reasonCodeSymbolicName = "SSH_OPEN_UNKNOWN_CHANNEL_TYPE";
1447:                    break;
1448:                case 4:
1449:                    reasonCodeSymbolicName = "SSH_OPEN_RESOURCE_SHORTAGE";
1450:                    break;
1451:                default:
1452:                    reasonCodeSymbolicName = "UNKNOWN REASON CODE ("
1453:                            + reasonCode + ")";
1454:                }
1455:
1456:                StringBuffer descriptionBuffer = new StringBuffer();
1457:                descriptionBuffer.append(description);
1458:
1459:                for (int i = 0; i < descriptionBuffer.length(); i++) {
1460:                    char cc = descriptionBuffer.charAt(i);
1461:
1462:                    if ((cc >= 32) && (cc <= 126))
1463:                        continue;
1464:                    descriptionBuffer.setCharAt(i, '\uFFFD');
1465:                }
1466:
1467:                synchronized (c) {
1468:                    c.EOF = true;
1469:                    c.state = Channel.STATE_CLOSED;
1470:                    c
1471:                            .setReasonClosed("The server refused to open the channel ("
1472:                                    + reasonCodeSymbolicName
1473:                                    + ", '"
1474:                                    + descriptionBuffer.toString() + "')");
1475:                    c.notifyAll();
1476:                }
1477:
1478:                if (log.isEnabled())
1479:                    log.log(50, "Got SSH_MSG_CHANNEL_OPEN_FAILURE (channel "
1480:                            + id + ")");
1481:            }
1482:
1483:            public void msgGlobalRequest(byte[] msg, int msglen)
1484:                    throws IOException {
1485:                /* Currently we do not support any kind of global request */
1486:
1487:                TypesReader tr = new TypesReader(msg, 0, msglen);
1488:
1489:                tr.readByte(); // skip packet type
1490:                String requestName = tr.readString();
1491:                boolean wantReply = tr.readBoolean();
1492:
1493:                if (wantReply) {
1494:                    byte[] reply_failure = new byte[1];
1495:                    reply_failure[0] = Packets.SSH_MSG_REQUEST_FAILURE;
1496:
1497:                    tm.sendAsynchronousMessage(reply_failure);
1498:                }
1499:
1500:                /* We do not clean up the requestName String - that is OK for debug */
1501:
1502:                if (log.isEnabled())
1503:                    log.log(80, "Got SSH_MSG_GLOBAL_REQUEST (" + requestName
1504:                            + ")");
1505:            }
1506:
1507:            public void msgGlobalSuccess() throws IOException {
1508:                synchronized (channels) {
1509:                    globalSuccessCounter++;
1510:                    channels.notifyAll();
1511:                }
1512:
1513:                if (log.isEnabled())
1514:                    log.log(80, "Got SSH_MSG_REQUEST_SUCCESS");
1515:            }
1516:
1517:            public void msgGlobalFailure() throws IOException {
1518:                synchronized (channels) {
1519:                    globalFailedCounter++;
1520:                    channels.notifyAll();
1521:                }
1522:
1523:                if (log.isEnabled())
1524:                    log.log(80, "Got SSH_MSG_REQUEST_FAILURE");
1525:            }
1526:
1527:            public void handleMessage(byte[] msg, int msglen)
1528:                    throws IOException {
1529:                if (msg == null) {
1530:                    if (log.isEnabled())
1531:                        log.log(50, "HandleMessage: got shutdown");
1532:
1533:                    synchronized (listenerThreads) {
1534:                        for (int i = 0; i < listenerThreads.size(); i++) {
1535:                            IChannelWorkerThread lat = (IChannelWorkerThread) listenerThreads
1536:                                    .elementAt(i);
1537:                            lat.stopWorking();
1538:                        }
1539:                        listenerThreadsAllowed = false;
1540:                    }
1541:
1542:                    synchronized (channels) {
1543:                        shutdown = true;
1544:
1545:                        for (int i = 0; i < channels.size(); i++) {
1546:                            Channel c = (Channel) channels.elementAt(i);
1547:                            synchronized (c) {
1548:                                c.EOF = true;
1549:                                c.state = Channel.STATE_CLOSED;
1550:                                c
1551:                                        .setReasonClosed("The connection is being shutdown");
1552:                                c.closeMessageRecv = true; /*
1553:                                 * You never know, perhaps
1554:                                 * we are waiting for a
1555:                                 * pending close message
1556:                                 * from the server...
1557:                                 */
1558:                                c.notifyAll();
1559:                            }
1560:                        }
1561:                        /* Works with J2ME */
1562:                        channels.setSize(0);
1563:                        channels.trimToSize();
1564:                        channels.notifyAll(); /* Notify global response waiters */
1565:                        return;
1566:                    }
1567:                }
1568:
1569:                switch (msg[0]) {
1570:                case Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
1571:                    msgChannelOpenConfirmation(msg, msglen);
1572:                    break;
1573:                case Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST:
1574:                    msgChannelWindowAdjust(msg, msglen);
1575:                    break;
1576:                case Packets.SSH_MSG_CHANNEL_DATA:
1577:                    msgChannelData(msg, msglen);
1578:                    break;
1579:                case Packets.SSH_MSG_CHANNEL_EXTENDED_DATA:
1580:                    msgChannelExtendedData(msg, msglen);
1581:                    break;
1582:                case Packets.SSH_MSG_CHANNEL_REQUEST:
1583:                    msgChannelRequest(msg, msglen);
1584:                    break;
1585:                case Packets.SSH_MSG_CHANNEL_EOF:
1586:                    msgChannelEOF(msg, msglen);
1587:                    break;
1588:                case Packets.SSH_MSG_CHANNEL_OPEN:
1589:                    msgChannelOpen(msg, msglen);
1590:                    break;
1591:                case Packets.SSH_MSG_CHANNEL_CLOSE:
1592:                    msgChannelClose(msg, msglen);
1593:                    break;
1594:                case Packets.SSH_MSG_CHANNEL_SUCCESS:
1595:                    msgChannelSuccess(msg, msglen);
1596:                    break;
1597:                case Packets.SSH_MSG_CHANNEL_FAILURE:
1598:                    msgChannelFailure(msg, msglen);
1599:                    break;
1600:                case Packets.SSH_MSG_CHANNEL_OPEN_FAILURE:
1601:                    msgChannelOpenFailure(msg, msglen);
1602:                    break;
1603:                case Packets.SSH_MSG_GLOBAL_REQUEST:
1604:                    msgGlobalRequest(msg, msglen);
1605:                    break;
1606:                case Packets.SSH_MSG_REQUEST_SUCCESS:
1607:                    msgGlobalSuccess();
1608:                    break;
1609:                case Packets.SSH_MSG_REQUEST_FAILURE:
1610:                    msgGlobalFailure();
1611:                    break;
1612:                default:
1613:                    throw new IOException(
1614:                            "Cannot handle unknown channel message "
1615:                                    + (msg[0] & 0xff));
1616:                }
1617:            }
1618:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.