diff --git a/README.md b/README.md
index 21b807e..d5f4d44 100644
--- a/README.md
+++ b/README.md
@@ -150,14 +150,15 @@ host-verified connection for another session.
### SFTP
-Called directly on a fresh connection, each SFTP method is one-shot: it opens
-its own channel and subsystem, runs the single operation, and closes. Downloads
-and uploads use `xstring` end to end:
+Use `zif_oassh_sftp_one_shot` on a fresh connection for one operation. It opens
+its own channel and subsystem, runs the operation, and closes the channel.
+Downloads and uploads use `xstring` end to end:
```abap
DATA lv_file TYPE xstring.
+DATA li_sftp TYPE REF TO zif_oassh_sftp_one_shot.
-lo_ssh = zcl_oassh=>connect(
+li_sftp = zcl_oassh=>connect(
iv_host = 'ssh.example.com'
iv_port = '22'
iv_user = 'deploy'
@@ -165,13 +166,13 @@ lo_ssh = zcl_oassh=>connect(
ii_host_verifier = lo_host_verifier ).
TRY.
- lv_file = lo_ssh->sftp_download(
+ lv_file = li_sftp->sftp_download(
iv_path = '/incoming/data.bin'
iv_timeout_seconds = 60 ).
CLEANUP.
- lo_ssh->close( ).
+ li_sftp->close( ).
ENDTRY.
-lo_ssh->close( ).
+li_sftp->close( ).
```
The public SFTP methods are:
@@ -190,24 +191,26 @@ file.
#### Multi-operation SFTP sessions
-To run several SFTP operations over a single authenticated connection, call
-`sftp_open` first. It performs the channel, subsystem, and INIT/VERSION
+To run several SFTP operations over a single authenticated connection, use
+`zif_oassh_sftp_session` and call `sftp_open` first. It performs the channel,
+subsystem, and INIT/VERSION
handshake once; the same `sftp_*` methods then run inside that session until
`sftp_close`. This avoids repeating the full SSH handshake — and, on APC, the
one-byte-per-frame cost of every handshake — for each operation:
```abap
-lo_ssh = zcl_oassh=>connect( ... ).
+DATA li_sftp TYPE REF TO zif_oassh_sftp_session.
+li_sftp = zcl_oassh=>connect( ... ).
TRY.
- lo_ssh->sftp_open( ).
- lt_names = lo_ssh->sftp_list( '/incoming' ).
- lv_file = lo_ssh->sftp_download( '/incoming/data.bin' ).
- ls_attrs = lo_ssh->sftp_stat( '/incoming/data.bin' ).
- lo_ssh->sftp_close( ).
+ li_sftp->sftp_open( ).
+ lt_names = li_sftp->sftp_list( '/incoming' ).
+ lv_file = li_sftp->sftp_download( '/incoming/data.bin' ).
+ ls_attrs = li_sftp->sftp_stat( '/incoming/data.bin' ).
+ li_sftp->sftp_close( ).
CLEANUP.
- lo_ssh->close( ).
+ li_sftp->close( ).
ENDTRY.
-lo_ssh->close( ).
+li_sftp->close( ).
```
One SFTP operation runs at a time, and the session is not reused across
diff --git a/abaplint.jsonc b/abaplint.jsonc
index d069487..52b005d 100644
--- a/abaplint.jsonc
+++ b/abaplint.jsonc
@@ -38,6 +38,9 @@
"begin_end_names": true,
"begin_single_include": true,
"call_transaction_authority_check": true,
+ "add_test_attributes": true,
+ "aff_and_xml": true,
+ "align_pseudo_comments": true,
"cds_parser_error": true,
"chain_mainly_declarations": true,
"check_abstract": true,
diff --git a/docs/interactive-exec.md b/docs/interactive-exec.md
index 0a1025f..26eec1c 100644
--- a/docs/interactive-exec.md
+++ b/docs/interactive-exec.md
@@ -7,8 +7,8 @@ response, decide, and write the next request while the command keeps
running. The canonical example is `git-upload-pack`, which GitHub exposes
to deploy keys: ref advertisement down, `want`/`done` up, packfile down.
-The interactive exec API keeps the session channel open and hands the
-byte streams to the caller:
+The `zif_oassh_interactive_exec` interface keeps the session channel open and
+hands the byte streams to the caller:
| Method | Purpose |
| --- | --- |
@@ -31,18 +31,20 @@ command's output stream has ended (the peer sent `CHANNEL_EOF` or the
connection closed). Callers therefore loop:
```abap
-DATA(lo_ssh) = zcl_oassh=>connect(
+DATA li_exec TYPE REF TO zif_oassh_interactive_exec.
+
+li_exec = zcl_oassh=>connect(
iv_host = 'github.com'
iv_port = '22'
iv_user = 'git'
iv_private_seed = lv_ed25519_seed " the deploy key
ii_host_verifier = li_verifier ).
-lo_ssh->exec_open( |git-upload-pack 'owner/repo.git'| ).
+li_exec->exec_open( |git-upload-pack 'owner/repo.git'| ).
DATA(lv_advertisement) = VALUE xstring( ).
-WHILE lo_ssh->exec_is_closed( ) = abap_false.
- DATA(lv_chunk) = lo_ssh->exec_read( ).
+WHILE li_exec->exec_is_closed( ) = abap_false.
+ DATA(lv_chunk) = li_exec->exec_read( ).
IF lv_chunk IS INITIAL.
EXIT. " timeout: decide whether the protocol layer has a complete unit
ENDIF.
@@ -50,9 +52,10 @@ WHILE lo_ssh->exec_is_closed( ) = abap_false.
" ... hand to a pkt-line parser, stop when it has the full advertisement
ENDWHILE.
-lo_ssh->exec_write( lv_want_request ). " pkt-lines: want, deepen, flush, done
+li_exec->exec_write( lv_want_request ). " pkt-lines: want, deepen, flush, done
" ... read the packfile with the same exec_read loop
-lo_ssh->exec_close( ).
+li_exec->exec_close( ).
+li_exec->close( ).
```
## Flow control
@@ -63,8 +66,8 @@ that do not fit are queued and sent automatically when the server's
`exec_eof( )` refuses to half-close while stdin is still queued, because
those bytes could never be delivered afterwards.
-Like every other operation on `zcl_oassh`, an interactive exec is the one
-operation of its connection object: `exec_open( )` on a connection that
+Like every other workflow, an interactive exec is the one operation of its
+connection object: `exec_open( )` on a connection that
already ran an operation raises the usual typed error.
## Scope
diff --git a/docs/sftp-sessions.md b/docs/sftp-sessions.md
index 5db604e..77c5a66 100644
--- a/docs/sftp-sessions.md
+++ b/docs/sftp-sessions.md
@@ -1,8 +1,8 @@
# Multi-operation SFTP sessions
-Each `sftp_*` method on `zcl_oassh` is one-shot by default: it authenticates,
-opens a session channel, starts the `sftp` subsystem, runs a single operation,
-and closes the channel. Every operation therefore pays for a full SSH handshake
+Each method on `zif_oassh_sftp_one_shot` authenticates, opens a session channel,
+starts the `sftp` subsystem, runs a single operation, and closes the channel.
+Every operation therefore pays for a full SSH handshake
and a fresh subsystem — expensive when a caller needs several operations in a
row, and especially so on APC, where each handshake is exchanged one byte per
frame.
@@ -12,12 +12,12 @@ the channel, subsystem, and INIT/VERSION handshake once; the same `sftp_*`
methods then run inside that single subsystem channel until `sftp_close`.
```abap
-DATA lo_ssh TYPE REF TO zcl_oassh.
-DATA lt_names TYPE zcl_oassh_sftp=>ty_names.
+DATA li_sftp TYPE REF TO zif_oassh_sftp_session.
+DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
DATA lv_data TYPE xstring.
-DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs.
+DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
-lo_ssh = zcl_oassh=>connect(
+li_sftp = zcl_oassh=>connect(
iv_host = 'ssh.example.com'
iv_port = '22'
iv_user = 'deploy'
@@ -25,18 +25,18 @@ lo_ssh = zcl_oassh=>connect(
ii_host_verifier = lo_host_verifier ).
TRY.
- lo_ssh->sftp_open( ). " channel + subsystem + INIT/VERSION
- lt_names = lo_ssh->sftp_list( '/incoming' ).
- lv_data = lo_ssh->sftp_download( '/incoming/data.bin' ).
- ls_attrs = lo_ssh->sftp_stat( '/incoming/data.bin' ).
- lo_ssh->sftp_rename(
+ li_sftp->sftp_open( ). " channel + subsystem + INIT/VERSION
+ lt_names = li_sftp->sftp_list( '/incoming' ).
+ lv_data = li_sftp->sftp_download( '/incoming/data.bin' ).
+ ls_attrs = li_sftp->sftp_stat( '/incoming/data.bin' ).
+ li_sftp->sftp_rename(
iv_old_path = '/incoming/data.bin'
iv_new_path = '/incoming/data.bin.done' ).
- lo_ssh->sftp_close( ). " channel close handshake
+ li_sftp->sftp_close( ). " channel close handshake
CLEANUP.
- lo_ssh->close( ).
+ li_sftp->close( ).
ENDTRY.
-lo_ssh->close( ).
+li_sftp->close( ).
```
## API
@@ -52,8 +52,9 @@ lo_ssh->close( ).
usual typed error, and a session is never reused across those other kinds or a
second channel.
-Without `sftp_open`, every `sftp_*` method behaves exactly as before — one-shot,
-one connection per operation — so existing callers are unaffected.
+Use `zif_oassh_sftp_one_shot` when no reusable session is needed. The concrete
+SFTP methods on `zcl_oassh` are implementation details; callers select one of
+the two SFTP interfaces explicitly.
## Semantics
diff --git a/examples/zoassh_example_sftp.prog.abap b/examples/zoassh_example_sftp.prog.abap
index 86ac392..202cdac 100644
--- a/examples/zoassh_example_sftp.prog.abap
+++ b/examples/zoassh_example_sftp.prog.abap
@@ -44,8 +44,8 @@ START-OF-SELECTION.
FORM run.
DATA lo_host_verifier TYPE REF TO zif_oassh_host_verifier.
- DATA lo_ssh TYPE REF TO zcl_oassh.
- DATA lt_names TYPE zcl_oassh_sftp=>ty_names.
+ DATA li_sftp TYPE REF TO zif_oassh_sftp_session.
+ DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
DATA lv_filename TYPE string.
DATA lv_data TYPE xstring.
DATA lv_preview TYPE string.
@@ -59,30 +59,30 @@ FORM run.
TRY.
* ii_random is optional on SAP: zcl_oassh defaults to zcl_oassh_random_secure,
* which draws from the kernel-backed secure random source.
- lo_ssh = zcl_oassh=>connect(
+ li_sftp = zcl_oassh=>connect(
iv_host = p_host
iv_port = p_port
iv_user = p_user
iv_password = p_pass
ii_host_verifier = lo_host_verifier ).
TRY.
- lo_ssh->sftp_open( p_tmout ).
+ li_sftp->sftp_open( p_tmout ).
* --- list a directory -----------------------------------------------------
- lt_names = lo_ssh->sftp_list(
+ lt_names = li_sftp->sftp_list(
iv_path = p_dir
iv_timeout_seconds = p_tmout ).
* --- download a file ------------------------------------------------------
- lv_data = lo_ssh->sftp_download(
+ lv_data = li_sftp->sftp_download(
iv_path = p_file
iv_timeout_seconds = p_tmout ).
- lo_ssh->sftp_close( p_tmout ).
+ li_sftp->sftp_close( p_tmout ).
CLEANUP.
- lo_ssh->close( ).
+ li_sftp->close( ).
ENDTRY.
- lo_ssh->close( ).
+ li_sftp->close( ).
WRITE: / 'listing of', p_dir.
SKIP.
diff --git a/scripts/check-public-api.test.mjs b/scripts/check-public-api.test.mjs
index fd3d3ae..530255b 100644
--- a/scripts/check-public-api.test.mjs
+++ b/scripts/check-public-api.test.mjs
@@ -4,6 +4,9 @@ import test from "node:test";
const publicSources = [
"../src/zcl_oassh.clas.abap",
+ "../src/zif_oassh_interactive_exec.intf.abap",
+ "../src/zif_oassh_sftp_one_shot.intf.abap",
+ "../src/zif_oassh_sftp_session.intf.abap",
"../src/platform/zif_oassh_socket.intf.abap",
];
diff --git a/src/zcl_oassh.clas.abap b/src/zcl_oassh.clas.abap
index 772c891..390949c 100644
--- a/src/zcl_oassh.clas.abap
+++ b/src/zcl_oassh.clas.abap
@@ -4,6 +4,10 @@ CLASS zcl_oassh DEFINITION
PUBLIC SECTION.
+ INTERFACES zif_oassh_interactive_exec.
+ INTERFACES zif_oassh_sftp_one_shot.
+ INTERFACES zif_oassh_sftp_session.
+
CLASS-METHODS connect
IMPORTING
iv_host TYPE string
@@ -27,29 +31,6 @@ CLASS zcl_oassh DEFINITION
VALUE(rv_output) TYPE string
RAISING
zcx_oassh_error.
-* Multi-operation SFTP session: sftp_open( ) performs the channel, subsystem
-* and INIT/VERSION handshake once, then the sftp_* methods below run inside
-* that single session until sftp_close( ). Without sftp_open( ) each sftp_*
-* method is one-shot (its own connection lifecycle), exactly as before.
-* See docs/sftp-sessions.md.
- METHODS sftp_open
- IMPORTING
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING
- zcx_oassh_error.
- METHODS sftp_close
- IMPORTING
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING
- zcx_oassh_error.
- METHODS sftp_download
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING
- VALUE(rv_data) TYPE xstring
- RAISING
- zcx_oassh_error.
METHODS shell
IMPORTING
iv_input TYPE xstring
@@ -61,97 +42,6 @@ CLASS zcl_oassh DEFINITION
VALUE(rv_output) TYPE xstring
RAISING
zcx_oassh_error.
-* Interactive exec: exec_open starts a command and returns while the channel
-* stays open, so the caller can interleave binary stdin and stdout, for
-* example to speak a request/response protocol such as git-upload-pack.
-* The conversation ends with exec_close. See docs/interactive-exec.md.
- METHODS exec_open
- IMPORTING
- iv_command TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING
- zcx_oassh_error.
- METHODS exec_write
- IMPORTING
- iv_data TYPE xstring
- RAISING
- zcx_oassh_error.
- METHODS exec_read
- IMPORTING
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING
- VALUE(rv_data) TYPE xstring
- RAISING
- zcx_oassh_error.
- METHODS exec_eof
- RAISING
- zcx_oassh_error.
- METHODS exec_close
- IMPORTING
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING
- zcx_oassh_error.
- METHODS exec_is_closed
- RETURNING
- VALUE(rv_closed) TYPE abap_bool.
- METHODS sftp_upload
- IMPORTING
- iv_path TYPE string
- iv_data TYPE xstring
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING
- zcx_oassh_error.
- METHODS sftp_stat
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING
- VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs
- RAISING
- zcx_oassh_error.
- METHODS sftp_lstat
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING
- VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs
- RAISING
- zcx_oassh_error.
- METHODS sftp_list
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING
- VALUE(rt_names) TYPE zcl_oassh_sftp=>ty_names
- RAISING
- zcx_oassh_error.
- METHODS sftp_mkdir
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING zcx_oassh_error.
- METHODS sftp_rmdir
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING zcx_oassh_error.
- METHODS sftp_remove
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING zcx_oassh_error.
- METHODS sftp_rename
- IMPORTING
- iv_old_path TYPE string
- iv_new_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RAISING zcx_oassh_error.
- METHODS sftp_realpath
- IMPORTING
- iv_path TYPE string
- iv_timeout_seconds TYPE i DEFAULT 300
- RETURNING VALUE(rs_name) TYPE zcl_oassh_sftp=>ty_name
- RAISING zcx_oassh_error.
METHODS get_stderr
RETURNING
VALUE(rv_output) TYPE string.
@@ -238,6 +128,95 @@ CLASS zcl_oassh DEFINITION
DATA mv_disconnected TYPE abap_bool.
DATA mv_disconnect_reason TYPE i.
+* Concrete implementations shared by the workflow interfaces.
+ METHODS exec_open
+ IMPORTING
+ iv_command TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS exec_write
+ IMPORTING iv_data TYPE xstring
+ RAISING zcx_oassh_error.
+ METHODS exec_read
+ IMPORTING iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rv_data) TYPE xstring
+ RAISING zcx_oassh_error.
+ METHODS exec_eof RAISING zcx_oassh_error.
+ METHODS exec_close
+ IMPORTING iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS exec_is_closed
+ RETURNING VALUE(rv_closed) TYPE abap_bool.
+ METHODS sftp_open
+ IMPORTING iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_close
+ IMPORTING iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_download
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rv_data) TYPE xstring
+ RAISING zcx_oassh_error.
+ METHODS sftp_upload
+ IMPORTING
+ iv_path TYPE string
+ iv_data TYPE xstring
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_stat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
+ RAISING zcx_oassh_error.
+ METHODS sftp_lstat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
+ RAISING zcx_oassh_error.
+ METHODS sftp_list
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names
+ RAISING zcx_oassh_error.
+ METHODS sftp_mkdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rmdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_remove
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rename
+ IMPORTING
+ iv_old_path TYPE string
+ iv_new_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_realpath
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name
+ RAISING zcx_oassh_error.
+
METHODS handle_transport_message
IMPORTING
iv_payload TYPE xstring
@@ -316,7 +295,7 @@ CLASS zcl_oassh DEFINITION
iv_lstat TYPE abap_bool
iv_timeout_seconds TYPE i
RETURNING
- VALUE(rs_attrs) TYPE zcl_oassh_sftp=>ty_attrs
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
RAISING
zcx_oassh_error.
METHODS sftp_mutation
@@ -356,6 +335,232 @@ ENDCLASS.
CLASS zcl_oassh IMPLEMENTATION.
+ METHOD zif_oassh_interactive_exec~exec_open.
+ exec_open(
+ iv_command = iv_command
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~exec_write.
+ exec_write( iv_data ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~exec_read.
+ rv_data = exec_read( iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~exec_eof.
+ exec_eof( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~exec_close.
+ exec_close( iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~exec_is_closed.
+ rv_closed = exec_is_closed( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~get_stderr.
+ rv_output = get_stderr( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~get_exit_status.
+ rv_status = get_exit_status( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~get_disconnect_reason.
+ rv_reason = get_disconnect_reason( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_interactive_exec~close.
+ close( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_download.
+ rv_data = sftp_download(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_upload.
+ sftp_upload(
+ iv_path = iv_path
+ iv_data = iv_data
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_stat.
+ rs_attrs = sftp_stat(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_lstat.
+ rs_attrs = sftp_lstat(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_list.
+ rt_names = sftp_list(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_mkdir.
+ sftp_mkdir(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_rmdir.
+ sftp_rmdir(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_remove.
+ sftp_remove(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_rename.
+ sftp_rename(
+ iv_old_path = iv_old_path
+ iv_new_path = iv_new_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~sftp_realpath.
+ rs_name = sftp_realpath(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~get_disconnect_reason.
+ rv_reason = get_disconnect_reason( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_one_shot~close.
+ close( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_open.
+ sftp_open( iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_close.
+ sftp_close( iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_download.
+ rv_data = sftp_download(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_upload.
+ sftp_upload(
+ iv_path = iv_path
+ iv_data = iv_data
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_stat.
+ rs_attrs = sftp_stat(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_lstat.
+ rs_attrs = sftp_lstat(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_list.
+ rt_names = sftp_list(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_mkdir.
+ sftp_mkdir(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_rmdir.
+ sftp_rmdir(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_remove.
+ sftp_remove(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_rename.
+ sftp_rename(
+ iv_old_path = iv_old_path
+ iv_new_path = iv_new_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~sftp_realpath.
+ rs_name = sftp_realpath(
+ iv_path = iv_path
+ iv_timeout_seconds = iv_timeout_seconds ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~get_disconnect_reason.
+ rv_reason = get_disconnect_reason( ).
+ ENDMETHOD.
+
+
+ METHOD zif_oassh_sftp_session~close.
+ close( ).
+ ENDMETHOD.
+
+
METHOD connect.
DATA li_socket TYPE REF TO zif_oassh_socket.
diff --git a/src/zcl_oassh.clas.testclasses.abap b/src/zcl_oassh.clas.testclasses.abap
index 8cf79c2..5eb83df 100644
--- a/src/zcl_oassh.clas.testclasses.abap
+++ b/src/zcl_oassh.clas.testclasses.abap
@@ -33,6 +33,7 @@ CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
METHODS exec_stream_guards FOR TESTING RAISING cx_static_check.
METHODS sftp_session_dispatch FOR TESTING RAISING cx_static_check.
METHODS sftp_session_guards FOR TESTING RAISING cx_static_check.
+ METHODS workflow_interfaces FOR TESTING RAISING cx_static_check.
METHODS sftp_api_state FOR TESTING RAISING cx_static_check.
METHODS empty_command_state FOR TESTING RAISING cx_static_check.
METHODS execute_early_failure FOR TESTING RAISING cx_static_check.
@@ -99,6 +100,47 @@ ENDCLASS.
CLASS ltcl_test IMPLEMENTATION.
+ METHOD workflow_interfaces.
+ DATA li_exec TYPE REF TO zif_oassh_interactive_exec.
+ DATA li_one_shot TYPE REF TO zif_oassh_sftp_one_shot.
+ DATA li_session TYPE REF TO zif_oassh_sftp_session.
+ DATA lx_error TYPE REF TO zcx_oassh_error.
+
+ li_exec = build_ssh( ).
+ TRY.
+ li_exec->exec_open(
+ iv_command = 'true'
+ iv_timeout_seconds = 0 ).
+ cl_abap_unit_assert=>fail( 'interactive interface did not delegate' ).
+ CATCH zcx_oassh_error INTO lx_error.
+ cl_abap_unit_assert=>assert_equals(
+ act = lx_error->if_t100_message~t100key-msgno
+ exp = '001' ).
+ ENDTRY.
+
+ li_one_shot = build_ssh( ).
+ TRY.
+ li_one_shot->sftp_download(
+ iv_path = '/tmp/file'
+ iv_timeout_seconds = 0 ).
+ cl_abap_unit_assert=>fail( 'one-shot interface did not delegate' ).
+ CATCH zcx_oassh_error INTO lx_error.
+ cl_abap_unit_assert=>assert_equals(
+ act = lx_error->if_t100_message~t100key-msgno
+ exp = '001' ).
+ ENDTRY.
+
+ li_session = build_ssh( ).
+ TRY.
+ li_session->sftp_open( 0 ).
+ cl_abap_unit_assert=>fail( 'session interface did not delegate' ).
+ CATCH zcx_oassh_error INTO lx_error.
+ cl_abap_unit_assert=>assert_equals(
+ act = lx_error->if_t100_message~t100key-msgno
+ exp = '001' ).
+ ENDTRY.
+ ENDMETHOD.
+
METHOD close_clears_secrets.
DATA lo_ssh TYPE REF TO zcl_oassh.
lo_ssh = build_ssh( ).
@@ -888,7 +930,7 @@ CLASS ltcl_test IMPLEMENTATION.
DATA lv_inbound_a TYPE xstring.
DATA lv_inbound_b TYPE xstring.
DATA lv_inbound TYPE xstring.
- DATA lt_names TYPE zcl_oassh_sftp=>ty_names.
+ DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
lo_mock = NEW #( ).
li_socket = lo_mock.
@@ -936,7 +978,7 @@ CLASS ltcl_test IMPLEMENTATION.
DATA li_socket TYPE REF TO zif_oassh_socket.
DATA li_random TYPE REF TO zif_oassh_random.
DATA li_verifier TYPE REF TO zif_oassh_host_verifier.
- DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs.
+ DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
lo_mock = NEW #( ).
li_socket = lo_mock.
@@ -2194,9 +2236,9 @@ CLASS ltcl_test IMPLEMENTATION.
DATA li_socket TYPE REF TO zif_oassh_socket.
DATA li_random TYPE REF TO zif_oassh_random.
DATA li_verifier TYPE REF TO zif_oassh_host_verifier.
- DATA lt_names TYPE zcl_oassh_sftp=>ty_names.
+ DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
DATA lv_data TYPE xstring.
- DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs.
+ DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
lo_mock = NEW #( ).
li_socket = lo_mock.
diff --git a/src/zcl_oassh_sftp.clas.abap b/src/zcl_oassh_sftp.clas.abap
index 3f4d19d..38fb26c 100644
--- a/src/zcl_oassh_sftp.clas.abap
+++ b/src/zcl_oassh_sftp.clas.abap
@@ -4,36 +4,6 @@ CLASS zcl_oassh_sftp DEFINITION
CREATE PUBLIC.
PUBLIC SECTION.
- TYPES ty_uint32 TYPE x LENGTH 4.
- TYPES ty_uint64 TYPE x LENGTH 8.
- TYPES:
- BEGIN OF ty_extension,
- extension_type TYPE xstring,
- extension_data TYPE xstring,
- END OF ty_extension.
- TYPES ty_extensions TYPE STANDARD TABLE OF ty_extension WITH EMPTY KEY.
- TYPES:
- BEGIN OF ty_attrs,
- flags TYPE ty_uint32,
- has_size TYPE abap_bool,
- size TYPE ty_uint64,
- has_uid_gid TYPE abap_bool,
- uid TYPE ty_uint32,
- gid TYPE ty_uint32,
- has_permissions TYPE abap_bool,
- permissions TYPE ty_uint32,
- has_acmodtime TYPE abap_bool,
- atime TYPE ty_uint32,
- mtime TYPE ty_uint32,
- extensions TYPE ty_extensions,
- END OF ty_attrs.
- TYPES:
- BEGIN OF ty_name,
- filename TYPE xstring,
- longname TYPE xstring,
- attrs TYPE ty_attrs,
- END OF ty_name.
- TYPES ty_names TYPE STANDARD TABLE OF ty_name WITH EMPTY KEY.
CONSTANTS c_max_packet_length TYPE i VALUE 262144.
CONSTANTS:
BEGIN OF c_state,
@@ -134,12 +104,12 @@ CLASS zcl_oassh_sftp DEFINITION
VALUE(rv_status) TYPE i.
METHODS get_attrs
RETURNING
- VALUE(rs_attrs) TYPE ty_attrs.
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs.
METHODS get_names
RETURNING
- VALUE(rt_names) TYPE ty_names.
+ VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names.
METHODS get_realpath
- RETURNING VALUE(rs_name) TYPE ty_name.
+ RETURNING VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name.
PRIVATE SECTION.
TYPES ty_request_ids TYPE SORTED TABLE OF i WITH UNIQUE KEY table_line.
@@ -177,9 +147,9 @@ CLASS zcl_oassh_sftp DEFINITION
DATA mv_upload_data TYPE xstring.
DATA mv_upload_position TYPE i.
DATA mv_write_length TYPE i.
- DATA ms_attrs TYPE ty_attrs.
- DATA mt_names TYPE ty_names.
- DATA ms_realpath TYPE ty_name.
+ DATA ms_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
+ DATA mt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
+ DATA ms_realpath TYPE zif_oassh_sftp_one_shot=>ty_name.
METHODS frame
IMPORTING
@@ -313,12 +283,12 @@ CLASS zcl_oassh_sftp DEFINITION
io_packet TYPE REF TO zcl_oassh_stream
iv_require_consumed TYPE abap_bool DEFAULT abap_true
RETURNING
- VALUE(rs_attrs) TYPE ty_attrs
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
RAISING
zcx_oassh_error.
CLASS-METHODS flag_is_set
IMPORTING
- iv_flags TYPE ty_uint32
+ iv_flags TYPE zif_oassh_sftp_one_shot=>ty_uint32
iv_bit TYPE i
RETURNING
VALUE(rv_set) TYPE abap_bool.
@@ -1021,7 +991,7 @@ CLASS zcl_oassh_sftp IMPLEMENTATION.
DATA lv_status TYPE i.
DATA lv_count TYPE i.
DATA lv_total TYPE i.
- DATA ls_name TYPE ty_name.
+ DATA ls_name TYPE zif_oassh_sftp_one_shot=>ty_name.
CASE mv_state.
WHEN c_state-opendir_pending.
CASE iv_type.
@@ -1115,11 +1085,11 @@ CLASS zcl_oassh_sftp IMPLEMENTATION.
METHOD parse_attrs.
* Section 5 fixes both field order and flag semantics. Unsupported v3 bits
* are a protocol error; raw unsigned values remain byte-exact for portable ABAP.
- DATA lv_flags TYPE ty_uint32.
+ DATA lv_flags TYPE zif_oassh_sftp_one_shot=>ty_uint32.
DATA lv_bit_index TYPE i.
DATA lv_bit TYPE c LENGTH 1.
DATA lv_count TYPE i.
- DATA ls_extension TYPE ty_extension.
+ DATA ls_extension TYPE zif_oassh_sftp_one_shot=>ty_extension.
lv_flags = io_packet->take( 4 ).
lv_bit_index = 2.
WHILE lv_bit_index <= 28.
diff --git a/src/zcl_oassh_sftp.clas.testclasses.abap b/src/zcl_oassh_sftp.clas.testclasses.abap
index a11373d..0c2bd39 100644
--- a/src/zcl_oassh_sftp.clas.testclasses.abap
+++ b/src/zcl_oassh_sftp.clas.testclasses.abap
@@ -492,7 +492,7 @@ CLASS ltcl_test IMPLEMENTATION.
METHOD stat_attrs.
* Sections 5 and 6.8: flags determine the exact order of every ATTRS field.
DATA lv_out TYPE xstring.
- DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs.
+ DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
lv_out = mo_sftp->start_stat( 'a' ).
lv_out = mo_sftp->receive( '000000050200000003' ).
cl_abap_unit_assert=>assert_equals(
@@ -548,7 +548,7 @@ CLASS ltcl_test IMPLEMENTATION.
METHOD stat_extensions.
* Unknown extension values are preserved as opaque byte strings.
DATA lv_out TYPE xstring.
- DATA ls_attrs TYPE zcl_oassh_sftp=>ty_attrs.
+ DATA ls_attrs TYPE zif_oassh_sftp_one_shot=>ty_attrs.
lv_out = mo_sftp->start_stat( 'a' ).
lv_out = mo_sftp->receive( '000000050200000003' ).
lv_out = mo_sftp->receive( '0000002169000000018000000000000002000000016100000000000000016200000002CCCC' ).
@@ -612,7 +612,7 @@ CLASS ltcl_test IMPLEMENTATION.
METHOD list_directory.
* OPENDIR -> HANDLE -> repeated READDIR/NAME -> EOF -> CLOSE/OK.
DATA lv_out TYPE xstring.
- DATA lt_names TYPE zcl_oassh_sftp=>ty_names.
+ DATA lt_names TYPE zif_oassh_sftp_one_shot=>ty_names.
lv_out = mo_sftp->start_list( 'd' ).
lv_out = mo_sftp->receive( '000000050200000003' ).
cl_abap_unit_assert=>assert_equals(
@@ -785,7 +785,7 @@ CLASS ltcl_test IMPLEMENTATION.
METHOD realpath_name.
DATA lv_out TYPE xstring.
- DATA ls_name TYPE zcl_oassh_sftp=>ty_name.
+ DATA ls_name TYPE zif_oassh_sftp_one_shot=>ty_name.
lv_out = mo_sftp->start_realpath( '.' ).
lv_out = mo_sftp->receive( '000000050200000003' ).
cl_abap_unit_assert=>assert_equals(
diff --git a/src/zif_oassh_interactive_exec.intf.abap b/src/zif_oassh_interactive_exec.intf.abap
new file mode 100644
index 0000000..e9a4567
--- /dev/null
+++ b/src/zif_oassh_interactive_exec.intf.abap
@@ -0,0 +1,46 @@
+INTERFACE zif_oassh_interactive_exec
+ PUBLIC.
+
+* Interactive command channel. Call exec_open( ) once, exchange binary data
+* with exec_write( ) and exec_read( ), then finish with exec_close( ). close( )
+* closes the underlying SSH socket and remains the final cleanup operation.
+ METHODS exec_open
+ IMPORTING
+ iv_command TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS exec_write
+ IMPORTING
+ iv_data TYPE xstring
+ RAISING
+ zcx_oassh_error.
+ METHODS exec_read
+ IMPORTING
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rv_data) TYPE xstring
+ RAISING
+ zcx_oassh_error.
+ METHODS exec_eof
+ RAISING
+ zcx_oassh_error.
+ METHODS exec_close
+ IMPORTING
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS exec_is_closed
+ RETURNING
+ VALUE(rv_closed) TYPE abap_bool.
+ METHODS get_stderr
+ RETURNING
+ VALUE(rv_output) TYPE string.
+ METHODS get_exit_status
+ RETURNING
+ VALUE(rv_status) TYPE i.
+ METHODS get_disconnect_reason
+ RETURNING
+ VALUE(rv_reason) TYPE i.
+ METHODS close.
+ENDINTERFACE.
diff --git a/src/zif_oassh_interactive_exec.intf.xml b/src/zif_oassh_interactive_exec.intf.xml
new file mode 100644
index 0000000..f4e1346
--- /dev/null
+++ b/src/zif_oassh_interactive_exec.intf.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ ZIF_OASSH_INTERACTIVE_EXEC
+ E
+ open-abap-ssh - Interactive exec
+ 2
+ 1
+ X
+
+
+
+
diff --git a/src/zif_oassh_sftp_one_shot.intf.abap b/src/zif_oassh_sftp_one_shot.intf.abap
new file mode 100644
index 0000000..8cad535
--- /dev/null
+++ b/src/zif_oassh_sftp_one_shot.intf.abap
@@ -0,0 +1,106 @@
+INTERFACE zif_oassh_sftp_one_shot
+ PUBLIC.
+
+* One SFTP operation per SSH connection. Each sftp_* method owns the SFTP
+* channel lifecycle. Call close( ) afterwards to close the underlying socket.
+ TYPES ty_uint32 TYPE x LENGTH 4.
+ TYPES ty_uint64 TYPE x LENGTH 8.
+ TYPES:
+ BEGIN OF ty_extension,
+ extension_type TYPE xstring,
+ extension_data TYPE xstring,
+ END OF ty_extension.
+ TYPES ty_extensions TYPE STANDARD TABLE OF ty_extension WITH EMPTY KEY.
+ TYPES:
+ BEGIN OF ty_attrs,
+ flags TYPE ty_uint32,
+ has_size TYPE abap_bool,
+ size TYPE ty_uint64,
+ has_uid_gid TYPE abap_bool,
+ uid TYPE ty_uint32,
+ gid TYPE ty_uint32,
+ has_permissions TYPE abap_bool,
+ permissions TYPE ty_uint32,
+ has_acmodtime TYPE abap_bool,
+ atime TYPE ty_uint32,
+ mtime TYPE ty_uint32,
+ extensions TYPE ty_extensions,
+ END OF ty_attrs.
+ TYPES:
+ BEGIN OF ty_name,
+ filename TYPE xstring,
+ longname TYPE xstring,
+ attrs TYPE ty_attrs,
+ END OF ty_name.
+ TYPES ty_names TYPE STANDARD TABLE OF ty_name WITH EMPTY KEY.
+ METHODS sftp_download
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rv_data) TYPE xstring
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_upload
+ IMPORTING
+ iv_path TYPE string
+ iv_data TYPE xstring
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_stat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE ty_attrs
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_lstat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE ty_attrs
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_list
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rt_names) TYPE ty_names
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_mkdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rmdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_remove
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rename
+ IMPORTING
+ iv_old_path TYPE string
+ iv_new_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_realpath
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING VALUE(rs_name) TYPE ty_name
+ RAISING zcx_oassh_error.
+ METHODS get_disconnect_reason
+ RETURNING
+ VALUE(rv_reason) TYPE i.
+ METHODS close.
+ENDINTERFACE.
diff --git a/src/zif_oassh_sftp_one_shot.intf.xml b/src/zif_oassh_sftp_one_shot.intf.xml
new file mode 100644
index 0000000..d3c76a8
--- /dev/null
+++ b/src/zif_oassh_sftp_one_shot.intf.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ ZIF_OASSH_SFTP_ONE_SHOT
+ E
+ open-abap-ssh - One-shot SFTP
+ 2
+ 1
+ X
+
+
+
+
diff --git a/src/zif_oassh_sftp_session.intf.abap b/src/zif_oassh_sftp_session.intf.abap
new file mode 100644
index 0000000..65b93f7
--- /dev/null
+++ b/src/zif_oassh_sftp_session.intf.abap
@@ -0,0 +1,87 @@
+INTERFACE zif_oassh_sftp_session
+ PUBLIC.
+
+* Reusable SFTP channel. Call sftp_open( ) once, run sequential sftp_*
+* operations, then call sftp_close( ) and close( ). Result types are owned by
+* zif_oassh_sftp_one_shot and referenced directly by both SFTP contracts.
+ METHODS sftp_open
+ IMPORTING
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_close
+ IMPORTING
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_download
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rv_data) TYPE xstring
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_upload
+ IMPORTING
+ iv_path TYPE string
+ iv_data TYPE xstring
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_stat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_lstat
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rs_attrs) TYPE zif_oassh_sftp_one_shot=>ty_attrs
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_list
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING
+ VALUE(rt_names) TYPE zif_oassh_sftp_one_shot=>ty_names
+ RAISING
+ zcx_oassh_error.
+ METHODS sftp_mkdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rmdir
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_remove
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_rename
+ IMPORTING
+ iv_old_path TYPE string
+ iv_new_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RAISING zcx_oassh_error.
+ METHODS sftp_realpath
+ IMPORTING
+ iv_path TYPE string
+ iv_timeout_seconds TYPE i DEFAULT 300
+ RETURNING VALUE(rs_name) TYPE zif_oassh_sftp_one_shot=>ty_name
+ RAISING zcx_oassh_error.
+ METHODS get_disconnect_reason
+ RETURNING
+ VALUE(rv_reason) TYPE i.
+ METHODS close.
+ENDINTERFACE.
diff --git a/src/zif_oassh_sftp_session.intf.xml b/src/zif_oassh_sftp_session.intf.xml
new file mode 100644
index 0000000..ddd0fbf
--- /dev/null
+++ b/src/zif_oassh_sftp_session.intf.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ ZIF_OASSH_SFTP_SESSION
+ E
+ open-abap-ssh - Reusable SFTP
+ 2
+ 1
+ X
+
+
+
+