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