From 86bc2e6ef86d9bc8137887717149e7fa80d2cb22 Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Mon, 13 Nov 2023 07:34:19 -0600 Subject: [PATCH 1/5] #411 add flush operation from is/jsch#39, with new config option to allow disabling in case it causes regressions. --- src/main/java/com/jcraft/jsch/Channel.java | 6 +++++- src/main/java/com/jcraft/jsch/ChannelSftp.java | 13 +++++++++++++ src/main/java/com/jcraft/jsch/JSch.java | 2 ++ src/main/java/com/jcraft/jsch/Session.java | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/jcraft/jsch/Channel.java b/src/main/java/com/jcraft/jsch/Channel.java index 5ebe102d..9474cf89 100644 --- a/src/main/java/com/jcraft/jsch/Channel.java +++ b/src/main/java/com/jcraft/jsch/Channel.java @@ -67,7 +67,11 @@ static Channel getChannel(String type, Session session) { ret = new ChannelForwardedTCPIP(); } if (type.equals("sftp")) { - ret = new ChannelSftp(); + ChannelSftp sftp = new ChannelSftp(); + boolean useWriteFlushWorkaround = + session.getConfig("use_sftp_write_flush_workaround").equals("yes"); + sftp.setUseWriteFlushWorkaround(useWriteFlushWorkaround); + ret = sftp; } if (type.equals("subsystem")) { ret = new ChannelSubsystem(); diff --git a/src/main/java/com/jcraft/jsch/ChannelSftp.java b/src/main/java/com/jcraft/jsch/ChannelSftp.java index c3dd3ac7..4848339e 100644 --- a/src/main/java/com/jcraft/jsch/ChannelSftp.java +++ b/src/main/java/com/jcraft/jsch/ChannelSftp.java @@ -157,6 +157,8 @@ public class ChannelSftp extends ChannelSession { private Charset fEncoding = StandardCharsets.UTF_8; private boolean fEncoding_is_utf8 = true; + private boolean useWriteFlushWorkaround = true; + private RequestQueue rq = new RequestQueue(16); /** @@ -181,6 +183,14 @@ public int getBulkRequests() { return rq.size(); } + public void setUseWriteFlushWorkaround(boolean useWriteFlushWorkaround) { + this.useWriteFlushWorkaround = useWriteFlushWorkaround; + } + + public boolean getUseWriteFlushWorkaround() { + return useWriteFlushWorkaround; + } + public ChannelSftp() { super(); lwsize_max = LOCAL_WINDOW_SIZE_MAX; @@ -754,6 +764,9 @@ public void write(byte[] d, int s, int len) throws IOException { try { int _len = len; while (_len > 0) { + if (useWriteFlushWorkaround && rwsize < 21 + handle.length + _len + 4) { + flush(); + } int sent = sendWRITE(handle, _offset[0], d, s, _len); writecount++; _offset[0] += sent; diff --git a/src/main/java/com/jcraft/jsch/JSch.java b/src/main/java/com/jcraft/jsch/JSch.java index 575a94fc..c1335964 100644 --- a/src/main/java/com/jcraft/jsch/JSch.java +++ b/src/main/java/com/jcraft/jsch/JSch.java @@ -228,6 +228,8 @@ public class JSch { config.put("try_additional_pubkey_algorithms", Util.getSystemProperty("jsch.try_additional_pubkey_algorithms", "yes")); config.put("enable_auth_none", Util.getSystemProperty("jsch.enable_auth_none", "yes")); + config.put("use_sftp_write_flush_workaround", + Util.getSystemProperty("jsch.use_sftp_write_flush_workaround", "yes")); config.put("CheckCiphers", Util.getSystemProperty("jsch.check_ciphers", "chacha20-poly1305@openssh.com")); diff --git a/src/main/java/com/jcraft/jsch/Session.java b/src/main/java/com/jcraft/jsch/Session.java index b0313f19..47cf3f19 100644 --- a/src/main/java/com/jcraft/jsch/Session.java +++ b/src/main/java/com/jcraft/jsch/Session.java @@ -3069,6 +3069,7 @@ private void applyConfig() throws JSchException { checkConfig(config, "enable_pubkey_auth_query"); checkConfig(config, "try_additional_pubkey_algorithms"); checkConfig(config, "enable_auth_none"); + checkConfig(config, "use_sftp_write_flush_workaround"); checkConfig(config, "cipher.c2s"); checkConfig(config, "cipher.s2c"); From 68831136473f04756402cb54000fe75cd3d4b87d Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Mon, 13 Nov 2023 07:34:44 -0600 Subject: [PATCH 2/5] Update dependencies. --- .mvn/wrapper/maven-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index ac184013..eacdc9ed 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.4/apache-maven-3.9.4-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar From 17c93eacbca4e05d7ae21eb0b18a8dc745bbd32b Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Mon, 13 Nov 2023 07:35:55 -0600 Subject: [PATCH 3/5] Add Java 21 to CI pipeline and also use it by default for building. --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/coverity.yml | 2 +- .github/workflows/javadoc.yml | 2 +- .github/workflows/maven.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 91aa6c1a..a9cd0a7b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,7 +36,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: '17' + java-version: '21' check-latest: true cache: 'maven' diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 6906b7c6..246e5967 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -12,7 +12,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: '17' + java-version: '21' check-latest: true cache: 'maven' - uses: vapier/coverity-scan-action@v1 diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml index 314f8ec9..d4250399 100644 --- a/.github/workflows/javadoc.yml +++ b/.github/workflows/javadoc.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: '17' + java-version: '21' check-latest: true - name: Build Javadoc run: mvn -B -V javadoc:javadoc --file pom.xml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d27a608b..48a9f8dd 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: ['8', '11', '17'] + java: ['8', '11', '17', '21'] steps: - uses: actions/checkout@v4 - name: Cache local Maven repository @@ -31,7 +31,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: '17' + java-version: '21' check-latest: true - name: Build with Maven run: mvn -B -V -DskipTests=true package --file pom.xml From 063b5d0a0815826e01dedd9ce1bb0a62526a6cf4 Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Mon, 13 Nov 2023 07:45:31 -0600 Subject: [PATCH 4/5] Switch CI pipelines to using maven wrapper and produce any execution error messages. --- .github/workflows/javadoc.yml | 2 +- .github/workflows/maven.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/javadoc.yml b/.github/workflows/javadoc.yml index d4250399..83d8ffdf 100644 --- a/.github/workflows/javadoc.yml +++ b/.github/workflows/javadoc.yml @@ -19,7 +19,7 @@ jobs: java-version: '21' check-latest: true - name: Build Javadoc - run: mvn -B -V javadoc:javadoc --file pom.xml + run: ./mvnw -B -V -e javadoc:javadoc - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@v4 with: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 48a9f8dd..8c624a1c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: java-version: '21' check-latest: true - name: Build with Maven - run: mvn -B -V -DskipTests=true package --file pom.xml + run: ./mvnw -B -V -e -DskipTests=true package - uses: actions/upload-artifact@v3 with: name: java-${{ matrix.java }}-jars @@ -49,7 +49,7 @@ jobs: java-version: ${{ matrix.java }} check-latest: true - name: Test with Maven - run: mvn -B -V -P coverage verify -Denforcer.skip=true -Dmaven.resources.skip=true -Dmaven.main.skip=true -Dassembly.skipAssembly=true -Dmaven.javadoc.skip=true -DskipITs=false --file pom.xml + run: ./mvnw -B -V -e -P coverage verify -Denforcer.skip=true -Dmaven.resources.skip=true -Dmaven.main.skip=true -Dassembly.skipAssembly=true -Dmaven.javadoc.skip=true -DskipITs=false - uses: actions/upload-artifact@v3 with: name: java-${{ matrix.java }}-testresults From d702bda9d3b0a607f6b1cbd8f274beab02c28b8e Mon Sep 17 00:00:00 2001 From: Jeremy Norris Date: Mon, 13 Nov 2023 09:45:35 -0600 Subject: [PATCH 5/5] #403 add a warning when Channel.getInputStream() or Channel.getExtInputStream() is called after Channel.connect(). --- src/main/java/com/jcraft/jsch/Channel.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/jcraft/jsch/Channel.java b/src/main/java/com/jcraft/jsch/Channel.java index 9474cf89..82abe288 100644 --- a/src/main/java/com/jcraft/jsch/Channel.java +++ b/src/main/java/com/jcraft/jsch/Channel.java @@ -208,6 +208,11 @@ public void setExtOutputStream(OutputStream out, boolean dontclose) { } public InputStream getInputStream() throws IOException { + Session _session = this.session; + if (_session != null && isConnected() && _session.getLogger().isEnabled(Logger.WARN)) { + _session.getLogger().log(Logger.WARN, "getInputStream() should be called before connect()"); + } + int max_input_buffer_size = 32 * 1024; try { max_input_buffer_size = Integer.parseInt(getSession().getConfig("max_input_buffer_size")); @@ -221,6 +226,12 @@ public InputStream getInputStream() throws IOException { } public InputStream getExtInputStream() throws IOException { + Session _session = this.session; + if (_session != null && isConnected() && _session.getLogger().isEnabled(Logger.WARN)) { + _session.getLogger().log(Logger.WARN, + "getExtInputStream() should be called before connect()"); + } + int max_input_buffer_size = 32 * 1024; try { max_input_buffer_size = Integer.parseInt(getSession().getConfig("max_input_buffer_size"));