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 > > >