Discussion:
[JSch-users] Pipe closed ChannelSftp
The Stake And Chain
2014-07-10 16:09:01 UTC
Permalink
Hello,

I'm using jsch-0.1.51, and I'm using ChannelSftp to get and put
PGP-encrypted data to a remote server that I do not control.

The put works perfectly, but with the get I'm having issues.

I initialize a session, and connect like so (some commenting has been
redacted):

private void initSftpConnection() throws JSchException {

initSftpParameters();

JSch jSch = new JSch();

try {


jSch.addIdentity(sftpPrivateKey);

session =
jSch.getSession(userName, remoteHost, Integer.parseInt(port));


session.setConfig("StrictHostKeyChecking", "no");

session.connect();

logger.debug("Session
established.");

sftp = (ChannelSftp)
session.openChannel("sftp");

sftp.connect();

} catch (JSchException e) {

logger.fatal("Error
establishing an SFTP connection", e);

throw e;

}

}



Since I'm dealing with encrypted data, I want to return an InputStream
which I pass to a decryption method, and I do so as described in the API
(once again, I've redeacted some comments and logging):

public InputStream getResponse() {

InputStream encryptedResponse = null;

try {

initSftpConnection();

sftp.cd
(remoteDownloadDirectory);


@SuppressWarnings("unchecked")

Vector<ChannelSftp.LsEntry>
remoteDirectoryEntries = sftp.ls(sftp.pwd());


Iterator<ChannelSftp.LsEntry> itr = remoteDirectoryEntries.iterator();

String downloadFileName =
"";

boolean isDownloadFileFound
= false;

ChannelSftp.LsEntry
remoteEntry = null;

while (itr.hasNext()) {

remoteEntry
= itr.next();


downloadFileName = remoteEntry.getFilename();

if
(downloadFileName.startsWith(classId)) {


isDownloadFileFound = true;


break;

}

}

if (isDownloadFileFound) {


logger.debug("Downloading file " + downloadFileName);


encryptedResponse = sftp.get(downloadFileName);


logger.debug("SFTP get was successful.");



}

} catch (Exception e) {

logger.fatal("Error in
getResponse ", e);

} finally {




sftp.disconnect();

session.disconnect();

}

return encryptedResponse;

}

The problem is, I get the following exception:

java.io.IOException: Pipe closed

at java.io.PipedInputStream.read(PipedInputStream.java:302)

at java.io.PipedInputStream.read(PipedInputStream.java:372)

at com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2527)

at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2553)

at
com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36)

at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1253)

at
java.io.BufferedInputStream.fill(BufferedInputStream.java:229)

at
java.io.BufferedInputStream.read(BufferedInputStream.java:248)

at
org.bouncycastle.openpgp.PGPUtil.getDecoderStream(Unknown Source)



The connection is established fine. I find the file, and it begins to
download.

Looking over the PipedInputStream source, it appears the Pipe Closed
exception is thrown in the read method of PipedInputStream if the close
method is invoked.

Is the PipedInputStream still trying to read after the session is closed?
I never explicitly call the close method on the stream, but it appears the
stream is indirectly closed when the disconnect method is called. Also, the
stream is making it to my decryption method. What am I missing?

Peter
thestakeandchain
2014-07-11 02:57:53 UTC
Permalink
I found my issue.

I use an OutputStream to write the InputStream to, and then convert back as needed.

Not elegant, but it worked.
Subject: Pipe closed ChannelSftp
Date: July 10, 2014 at 12:09:01 EDT
Hello,
I'm using jsch-0.1.51, and I'm using ChannelSftp to get and put PGP-encrypted data to a remote server that I do not control.
The put works perfectly, but with the get I'm having issues.
private void initSftpConnection() throws JSchException {
initSftpParameters();
JSch jSch = new JSch();
try {
jSch.addIdentity(sftpPrivateKey);
session = jSch.getSession(userName, remoteHost, Integer.parseInt(port));
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
logger.debug("Session established.");
sftp = (ChannelSftp) session.openChannel("sftp");
sftp.connect();
} catch (JSchException e) {
logger.fatal("Error establishing an SFTP connection", e);
throw e;
}
}
public InputStream getResponse() {
InputStream encryptedResponse = null;
try {
initSftpConnection();
sftp.cd(remoteDownloadDirectory);
@SuppressWarnings("unchecked")
Vector<ChannelSftp.LsEntry> remoteDirectoryEntries = sftp.ls(sftp.pwd());
Iterator<ChannelSftp.LsEntry> itr = remoteDirectoryEntries.iterator();
String downloadFileName = "";
boolean isDownloadFileFound = false;
ChannelSftp.LsEntry remoteEntry = null;
while (itr.hasNext()) {
remoteEntry = itr.next();
downloadFileName = remoteEntry.getFilename();
if (downloadFileName.startsWith(classId)) {
isDownloadFileFound = true;
break;
}
}
if (isDownloadFileFound) {
logger.debug("Downloading file " + downloadFileName);
encryptedResponse = sftp.get(downloadFileName);
logger.debug("SFTP get was successful.");
}
} catch (Exception e) {
logger.fatal("Error in getResponse ", e);
} finally {
sftp.disconnect();
session.disconnect();
}
return encryptedResponse;
}
java.io.IOException: Pipe closed
at java.io.PipedInputStream.read(PipedInputStream.java:302)
at java.io.PipedInputStream.read(PipedInputStream.java:372)
at com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2527)
at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2553)
at com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36)
at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1253)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:229)
at java.io.BufferedInputStream.read(BufferedInputStream.java:248)
at org.bouncycastle.openpgp.PGPUtil.getDecoderStream(Unknown Source)
The connection is established fine. I find the file, and it begins to download.
Looking over the PipedInputStream source, it appears the Pipe Closed exception is thrown in the read method of PipedInputStream if the close method is invoked.
Is the PipedInputStream still trying to read after the session is closed? I never explicitly call the close method on the stream, but it appears the stream is indirectly closed when the disconnect method is called. Also, the stream is making it to my decryption method. What am I missing?
Peter
Jung, Volker
2014-07-11 09:15:21 UTC
Permalink
Hello Peter,

the input stream becomes invalid the moment you close the channel to the remote host. Whether you transfer encrypted data or not is irrelevant for the subject, but I understand that you want to process the received data "on the fly".
Simply keep the channel open until you have completed processing the data and close it afterwards.

Have a look at your InputStream-OutputStream solution: if you're using some 3rd party lib, it could be that the conversion streams the input into local memory, so you're not reading data directly from the remote source.

Greetings
Volker


Von: thestakeandchain [mailto:***@gmail.com]
Gesendet: Freitag, 11. Juli 2014 04:58
An: jsch-***@lists.sourceforge.net
Betreff: [JSch-users] Fwd: Pipe closed ChannelSftp

I found my issue.

I use an OutputStream to write the InputStream to, and then convert back as needed.

Not elegant, but it worked.



Begin forwarded message:


From: The Stake And Chain <***@gmail.com<mailto:***@gmail.com>>
Subject: Pipe closed ChannelSftp
Date: July 10, 2014 at 12:09:01 EDT
To: jsch-***@lists.sourceforge.net<mailto:jsch-***@lists.sourceforge.net>


Hello,


I'm using jsch-0.1.51, and I'm using ChannelSftp to get and put PGP-encrypted data to a remote server that I do not control.


The put works perfectly, but with the get I'm having issues.


I initialize a session, and connect like so (some commenting has been redacted):


private void initSftpConnection() throws JSchException {


initSftpParameters();


JSch jSch = new JSch();


try {


jSch.addIdentity(sftpPrivateKey);

session = jSch.getSession(userName, remoteHost, Integer.parseInt(port));


session.setConfig("StrictHostKeyChecking", "no");


session.connect();

logger.debug("Session established.");


sftp = (ChannelSftp) session.openChannel("sftp");

sftp.connect();


} catch (JSchException e) {

logger.fatal("Error establishing an SFTP connection", e);

throw e;

}

}


Since I'm dealing with encrypted data, I want to return an InputStream which I pass to a decryption method, and I do so as described in the API (once again, I've redeacted some comments and logging):


public InputStream getResponse() {


InputStream encryptedResponse = null;


try {


initSftpConnection();


sftp.cd<http://sftp.cd/>(remoteDownloadDirectory);


@SuppressWarnings("unchecked")

Vector<ChannelSftp.LsEntry> remoteDirectoryEntries = sftp.ls<http://sftp.ls/>(sftp.pwd());

Iterator<ChannelSftp.LsEntry> itr = remoteDirectoryEntries.iterator();


String downloadFileName = "";

boolean isDownloadFileFound = false;

ChannelSftp.LsEntry remoteEntry = null;


while (itr.hasNext()) {

remoteEntry = itr.next();

downloadFileName = remoteEntry.getFilename();


if (downloadFileName.startsWith(classId)) {

isDownloadFileFound = true;

break;

}

}


if (isDownloadFileFound) {


logger.debug("Downloading file " + downloadFileName);

encryptedResponse = sftp.get(downloadFileName);

logger.debug("SFTP get was successful.");


}


} catch (Exception e) {

logger.fatal("Error in getResponse ", e);

} finally {


sftp.disconnect();

session.disconnect();

}


return encryptedResponse;

}


The problem is, I get the following exception:


java.io.IOException: Pipe closed

at java.io.PipedInputStream.read(PipedInputStream.java:302)

at java.io.PipedInputStream.read(PipedInputStream.java:372)

at com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2527)

at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2553)

at com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36)

at com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1253)

at java.io.BufferedInputStream.fill(BufferedInputStream.java:229)

at java.io.BufferedInputStream.read(BufferedInputStream.java:248)

at org.bouncycastle.openpgp.PGPUtil.getDecoderStream(Unknown Source)


The connection is established fine. I find the file, and it begins to download.


Looking over the PipedInputStream source, it appears the Pipe Closed exception is thrown in the read method of PipedInputStream if the close method is invoked.


Is the PipedInputStream still trying to read after the session is closed? I never explicitly call the close method on the stream, but it appears the stream is indirectly closed when the disconnect method is called. Also, the stream is making it to my decryption method. What am I missing?


Peter

Loading...