📄 ssh2transport.java
字号:
public String getClientVersion() { return clientVersion; } /** * Gets the server's version string. * * @return the server's version string. */ public String getServerVersion() { return serverVersion; } /** * Gets our preferences. * * @return our preferences. */ public SSH2Preferences getOurPreferences() { return ourPrefs; } /** * Gets the preferences peer want. * * @return peer's preferences. */ public SSH2Preferences getPeerPreferences() { return peerPrefs; } /** * Sets the event handler to use. * * @param eventHandler the event handler to use. */ public void setEventHandler(SSH2TransportEventHandler eventHandler) { if(eventHandler != null) { this.eventHandler = eventHandler; } } /** * Gets the event handler currently in use. * * @return the event handler currently in use. */ public SSH2TransportEventHandler getEventHandler() { return eventHandler; } /** * Gets the log handler currently in use. * * @return the log handler currently in use. */ public Log getLog() { return tpLog; } /** * Sets the log handler to use. * * @param the log handler to use */ public void setLog(Log log) { tpLog = log; } /** * Checks whether we are a server or a client. * * @return a boolean indicating if we are a server or not. */ public boolean isServer() { return weAreAServer; } /** * Gets the <code>SecureRandom</code> currently in use. * * @return the <code>SecureRandom</code> in use. */ public SecureRandom getSecureRandom() { return tpRand; } /** * Gets the <code>SSH2Compressor</code> currently in use for the * receiver. * * @return the <code>SSH2Compressor</code> in use, * <code>null</code> if none. */ public SSH2Compressor getRxCompressor() { return rxContext.compressor; } /** * Gets the <code>SSH2Compressor</code> currently in use for the * transmitter. * * @return the <code>SSH2Compressor</code> in use, * <code>null</code> if none. */ public SSH2Compressor getTxCompressor() { return txContext.compressor; } /** * Sets the <code>SSH2UserAuth</code> to use for the user authenticaton * stage. The user authentication service is started from the class * <code>SSH2UserAuth</code> through the method <code>requestService</code>. * * @param userAuth the userAuth layer */ public void setUserAuth(SSH2UserAuth userAuth) { this.userAuth = userAuth; } /** * Requests the given service (currently the only service defined is the * "ssh-userauth" service which starts the user authentication). * * @param service the name of the service to request */ public void requestService(String service) { SSH2TransportPDU pdu = SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_SERVICE_REQUEST); pdu.writeString(service); transmit(pdu); } /** * Sets the <code>SSH2Connection</code> to use for the connection layer. All * actions after this stage are made through the connection layer. * * @param connection the connection layer */ public void setConnection(SSH2Connection connection) { this.connection = connection; } /** * Starts a key exchange with the preferences set in the constructor. If a * key exchange is allready in progress this call have no effect. * * @exception SSH2Exception if a fatal error occurs. */ public void startKeyExchange() throws SSH2Exception { this.startKeyExchange(ourPrefs); } /** * Starts a key exchange with the given preferences (i.e. change to new * preferences and negotiate these with the peer). If a key exchange is * allready in progress this call have no effect. * * @param newPrefs the new preferences to use * * @exception SSH2Exception if a fatal error occurs */ public void startKeyExchange(SSH2Preferences newPrefs) throws SSH2Exception { synchronized(keyExchangeMonitor) { if(!keyExchangeInProgress) { if(incompatibleCantReKey && (peerPrefs != null)) { throw new SSH2FatalException("Error, peer '" + (weAreAServer ? clientVersion : serverVersion) + "' doesn't support re-keying"); } ourPrefs = newPrefs; keyExchangeInProgress = true; if(incompatibleRijndael) { removeRijndael(); } txQueue.disable(); rxNumPacketsSinceKEX = 0; txNumPacketsSinceKEX = 0; rxNumBytesSinceKEX = 0; txNumBytesSinceKEX = 0; sendKEXINIT(); } } } /** * Waits (blocks) for key exchange to complete (if not in progress returns * immediately). * * @return a boolean indicating if key exchange was successful or not. */ public boolean waitForKEXComplete() { synchronized(keyExchangeMonitor) { if(keyExchangeInProgress) { try { keyExchangeMonitor.wait(); } catch (InterruptedException e) { /* don't care, someone interrupted us on purpose */ } } return keyExchangeOk; } } /** * Checks if key exchange is currently in progress. * * @return a boolean indicating if key exchange is in progress or not. */ public boolean keyExchangeInProgress() { return keyExchangeInProgress; } /** * Checks if currently connected to a server. * * @return a boolean indicating if we are connected or not. */ public boolean isConnected() { return isConnected; } /** * Gets the message describing why transport was disconnected. Useful when * an error occurs and we are not hooked up with an eventhandler to see it * (e.g. when an error occurs in the key exchange it's only reported as a * disconnect reason). * * @return the disconnect message or <code>null</code> if still connected */ public String getDisconnectMessage() { String msg = null; synchronized(disconnectMonitor) { if(!isConnected) { msg = disconnectMessage; } } return msg; } /** * Sends an IGNORE packet (as defined in the protocol spec.) with the given * data as payload. * * @param data a byte array containing the payload */ public void sendIgnore(byte[] data) { sendIgnore(data, 0, data.length); } /** * Sends an IGNORE packet (as defined in the protocol spec.) with the given * data as payload. * * @param data a byte array containing the payload * @param off offset in <code>data</code> where payload starts * @param len length of payload */ public void sendIgnore(byte[] data, int off, int len) { SSH2TransportPDU pdu = SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_IGNORE); pdu.writeString(data, off, len); transmit(pdu); } /** * Sends a DEBUG packet (as defined in the protocol spec.) with the given * message. * * @param alwaysDisp boolean indicating whether this message must always be * displayed or not. * @param message the debug message to send * @param language the language tag to use */ public void sendDebug(boolean alwaysDisp, String message, String language) { SSH2TransportPDU pdu = SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_DEBUG); pdu.writeBoolean(alwaysDisp); pdu.writeString(message); pdu.writeString(language); transmit(pdu); } /** * Enables keep-alive function which sends IGNORE packets on the given time * interval to prevent the connection from beeing timed out (e.g. because of * TCP connection subject to idle-timeouts in a firewall). * * @param intervalSeconds interval time in seconds */ public void enableKeepAlive(int intervalSeconds) { if(heartbeat != null && heartbeat.isRunning()) { heartbeat.setInterval(intervalSeconds); } else if(intervalSeconds > 0) { heartbeat = new KeepAliveThread(intervalSeconds); } } /** * Disables keep-alive function. */ public void disableKeepAlive() { if(heartbeat != null) { heartbeat.stop(); } heartbeat = null; } private void kexComplete(boolean noError) { synchronized(keyExchangeMonitor) { keyExchangeInProgress = false; keyExchangeOk = noError; keyExchangeMonitor.notifyAll(); if(noError) { eventHandler.kexComplete(this); } } } private void authTerminate() { if(userAuth != null) { userAuth.terminate(); } } /** * Transmits the given PDU if we are connected. The PDU is put in a queue * which is processed by the internal threads hence this call is can only * block in extreme cases since all internal queues are subject to flow * control to prevent memory from beeing exhausted. * * @param pdu PDU to send */ public void transmit(SSH2TransportPDU pdu) { if(isConnected) { txQueue.putLast(pdu); } } /** * Transmits the given PDU without checking if we are connected. This * version of transmit writes the PDU directly to the * <code>OutputStream</code> to the peer, hence it can only be used when * the transmitter is not running. * * @param pdu PDU to send * * @exception SSH2Exception if an I/O exception or other fatal error occurs */ public synchronized void transmitInternal(SSH2TransportPDU pdu) throws SSH2Exception { if(DEBUG_ALL_TX) tpLog.debug2("SSH2Transport", "transmitInternal", "sending message of type: " + SSH2.msgTypeString(pdu.pktType), pdu.getData(), pdu.getPayloadOffset(), pdu.getPayloadLength()); try { pdu.writeTo(tpOut, txSeqNum++, txContext, tpRand); } catch (ShortBufferException e) { throw new SSH2FatalException("Internal error/bug: " + e.getMessage()); } catch (IOException e) { throw new SSH2FatalException("Couldn't write packet of type " + SSH2.msgTypeString(pdu.pktType), e); } } /** * Disconnects from peer using the DISCONNECT packet type with the given * reason and description. See the class <code>SSH2</code> for reason codes. * * @param reason the reason code * @param description the textual description for the cause of disconnect * * @see SSH2 */ public void fatalDisconnect(int reason, String description) { disconnectInternal(reason, description, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } /** * Disconnects from peer using the DISCONNECT packet type with the * reason code DISCONNECT_BY_APPLICATION and the given description. * * @param description the textual description for the cause of disconnect */ public void normalDisconnect(String description) { disconnectInternal(SSH2.DISCONNECT_BY_APPLICATION, description, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } private void disconnectInternal(int reason, String description, String languageTag, boolean fromPeer) { synchronized(disconnectMonitor) { if(!isConnected) { return; } isConnected = false; disconnectMessage = description; } if(fromPeer) { eventHandler.peerDisconnect(this, reason, description, languageTag); tpLog.warning("SSH2Transport", "disconnect: " + description); } else if(reason == SSH2.DISCONNECT_BY_APPLICATION) { eventHandler.normalDisconnect(this, description, languageTag); tpLog.notice("SSH2Transport", "disconnect: " + description); } else { eventHandler.fatalDisconnect(this, reason, description, languageTag); tpLog.error("SSH2Transport", "disconnectInternal", "disconnect: " + description); } if(!fromPeer && isTxUp) { // // !!! Pathological condition: tx may be exiting, will cause bug // txQueue.disable(); SSH2TransportPDU pdu = SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_DISCONNECT); pdu.writeInt(reason); pdu.writeString(description); pdu.writeString(""); // !!! TODO: Handle the language try { transmitInternal(pdu); } catch (SSH2Exception e) { tpLog.message(Log.LEVEL_ERROR, "SSH2Transport",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -