Hi Dennis,

thank you, it appears that this might then be a bug introduced in 2.0.0 (or
earlier). I managed to work around it for the time being by implementing a
custom SftpEventListener that throws an exception when a failed
closed()-event is triggered. Though definitely a hack, the client now ends
up receiving an error.

Regards,
Matthias

On Mon, 10 Sep 2018 at 14:21, Dennis van der Laan <d.g.van.der.l...@rug.nl>
wrote:

> Hi Matthias,
>
> We're doing the same, using sshd-core-1.2.0: we implemented our own
> FileChannel and throw an IOException in implCloseChannel when the uploaded
> file (in our case an XML-file) is not valid. This works as expected. I
> haven't tried 2.0.0, but might it be a bug in the new implementation?
>
> Best,
> Dennis
>
> On Mon, 10 Sep 2018 at 13:06, Matthias Hjalmarsson <matth...@yacc.se>
> wrote:
>
> > Hi,
> >
> > as a short backstory, we are looking at providing a SFTP endpoint for
> > legacy clients where they can upload files to a single root/default
> > directory and have them dynamically forwarded internally correctly. For
> > this purpose, all operations / file systems will be purely virtual. Even
> > listing of files won't be supported, just an upload operation (the root
> > directory will always appear to be empty).
> >
> > When a file is finished uploaded (into server memory), we want to push
> the
> > file to an internal service. For the sake of this question, let's just
> say
> > it's a simple REST service that we push to. Workflow is basically:
> >
> > 1) User connects and is authenticated
> > 2) Root directory appears to be empty
> > 3) PUT <some file>
> > 4) File is uploaded to server into server's memory
> > 5) When upload is finished, server pushes file to its correct final
> > destination
> > 6) Client receives OK
> >
> > We have a working proof-of-concept of this that works really well. To do
> > this, we implemented a minimal NIO FileSystem.
> >
> > The problem we are having is when [5] fails. The service we are pushing
> to
> > might be down, and then we want the client to get an error as well (=
> > please try again later). However, the problem is that we can not get the
> > server to report anything but success which means the client will think
> it
> > went through and the server is left with a file it couldn't process. We
> > don't want to have an internal retry-functionality inside the server but
> to
> > have the whole use-case synchronized.
> >
> > To get back to the question, I have a hard time know if this is due to
> > incorrect usage of NIO FileSystem from my part, or if perhaps SSHD
> doesn't
> > support this usecase.
> >
> > Our basic strategy is to eventually create a custom implementation of
> > FileChannel when FileSystemProvider#newFileChannel is called. Via
> debugging
> > inspection this appears to be callback we get on our FileSystemProvider
> > when an upload is initiated. This implementation handles the write()
> > operations to write the bytes into a local byte[], and then when
> eventually
> > UploadFileChannel#implCloseChannel() is called the byte[] is pushed.
> >
> > implCloseChannel() can throw an IOException, but this doesn't seem to
> > matter. Regardless, from the client's point-of-view it doesn't matter if
> > this call is successful or not. Looking at the code, I can step in
> > SSHD-SFTP into:
> >
> > Here, it seems like SSH_FXP_CLOSE would be sent if the closing of the
> > handle is not successful. I'm not sure if that would be the proper way of
> > reporting problems to the client, but regardless, it looks like this code
> > path isn't used. Because doClose(int, String) is called in the try-block,
> > and this code itself catch IOException in order to make callback to
> > listener. Should perhaps IOException be rethrown there?
> >
> > protected void doClose(Buffer buffer, int id) throws IOException {
> > String handle = buffer.getString();
> > try {
> > doClose(id, handle);
> > } catch (IOException | RuntimeException e) {
> > sendStatus(prepareReply(buffer), id, e, SftpConstants.SSH_FXP_CLOSE,
> > handle);
> > return;
> > }
> >
> > sendStatus(prepareReply(buffer), id, SftpConstants.SSH_FX_OK, "", "");
> > }
> > @Override
> > protected void doClose(int id, String handle) throws IOException {
> > Handle h = handles.remove(handle);
> > ServerSession session = getServerSession();
> > if (log.isDebugEnabled()) {
> > log.debug("doClose({})[id={}] SSH_FXP_CLOSE (handle={}[{}])",
> >   session, id, handle, h);
> > }
> >
> > Handle nodeHandle = validateHandle(handle, h, Handle.class);
> > SftpEventListener listener = getSftpEventListenerProxy();
> > try {
> > listener.closing(session, handle, nodeHandle);
> > nodeHandle.close();
> > listener.closed(session, handle, nodeHandle, null);
> > } catch (IOException | RuntimeException e) {
> > listener.closed(session, handle, nodeHandle, e);
> > }
> > }
> >
> > Or am I going about this the wrong way? I'm using apache-sshd-2.0.0.
> >
> > Thanks in advance!
> >
> > // Matthias
> >
>

Reply via email to