network-infra-utility 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/CHANGELOG.md +31 -4
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +70 -0
  6. data/Rakefile +1 -1
  7. data/bin/dns-query +834 -0
  8. data/bin/geo-doc +135 -0
  9. data/bin/geo-get +1 -1
  10. data/document/ASNum/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +242 -0
  11. data/document/DNSQuery/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +248 -0
  12. data/document/Geo/345/221/275/344/273/244/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +441 -0
  13. data/document/IP/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +297 -0
  14. data/document/MAC/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +296 -0
  15. data/document/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/344/275/277/347/224/250/346/226/271/346/263/225.md +764 -0
  16. data/network-infra-utility.gemspec +4 -2
  17. data/network.rb +3 -1
  18. data/service/geodb/GeoAPI.md +1 -0
  19. data/service/geodb/geodb.rb +278 -1
  20. data/service/ssh/README.md +942 -0
  21. data/service/ssh/bin/ssh-client +198 -0
  22. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/345/212/237/350/203/275/351/234/200/346/261/202/346/226/207/346/241/243.md +292 -0
  23. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/257/246/347/273/206/350/256/276/350/256/241/346/226/207/346/241/243.md +1521 -0
  24. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/275/257/344/273/266/350/256/276/350/256/241/346/226/207/346/241/243.md +2493 -0
  25. data/service/ssh/ext/ssh_core/bin/ssh_core.cmd +28 -0
  26. data/service/ssh/ext/ssh_core/config/sys.config +0 -0
  27. data/service/ssh/ext/ssh_core/config/vm.args +0 -0
  28. data/service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM +1 -0
  29. data/service/ssh/ext/ssh_core/local_deps/jsx/LICENSE +21 -0
  30. data/service/ssh/ext/ssh_core/local_deps/jsx/README.md +696 -0
  31. data/service/ssh/ext/ssh_core/local_deps/jsx/VERSION +1 -0
  32. data/service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz +0 -0
  33. data/service/ssh/ext/ssh_core/local_deps/jsx/metadata.config +15 -0
  34. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.config +17 -0
  35. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock +1 -0
  36. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src +10 -0
  37. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl +506 -0
  38. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl +393 -0
  39. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl +18 -0
  40. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl +81 -0
  41. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl +1909 -0
  42. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl +116 -0
  43. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl +1214 -0
  44. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl +408 -0
  45. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl +389 -0
  46. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl +121 -0
  47. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl +506 -0
  48. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl +393 -0
  49. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl +18 -0
  50. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl +81 -0
  51. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl +1909 -0
  52. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl +116 -0
  53. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl +1214 -0
  54. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl +408 -0
  55. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl +389 -0
  56. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl +121 -0
  57. data/service/ssh/ext/ssh_core/rebar.config +24 -0
  58. data/service/ssh/ext/ssh_core/rebar.lock +1 -0
  59. data/service/ssh/ext/ssh_core/src/ssh_auth_engine.erl +156 -0
  60. data/service/ssh/ext/ssh_core/src/ssh_channel_stm.erl +232 -0
  61. data/service/ssh/ext/ssh_core/src/ssh_codec.erl +83 -0
  62. data/service/ssh/ext/ssh_core/src/ssh_conn_sup.erl +48 -0
  63. data/service/ssh/ext/ssh_core/src/ssh_conn_worker.erl +535 -0
  64. data/service/ssh/ext/ssh_core/src/ssh_core.app.src +36 -0
  65. data/service/ssh/ext/ssh_core/src/ssh_core_app.erl +11 -0
  66. data/service/ssh/ext/ssh_core/src/ssh_core_sup.erl +46 -0
  67. data/service/ssh/ext/ssh_core/src/ssh_infra_sup.erl +104 -0
  68. data/service/ssh/ext/ssh_core/src/ssh_ipc.hrl +80 -0
  69. data/service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl +94 -0
  70. data/service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl +467 -0
  71. data/service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl +95 -0
  72. data/service/ssh/ext/ssh_core/src/ssh_jump_chain.erl +101 -0
  73. data/service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl +222 -0
  74. data/service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl +67 -0
  75. data/service/ssh/ext/ssh_core/src/ssh_port_fwd.erl +225 -0
  76. data/service/ssh/ext/ssh_core/src/ssh_sftp_session.erl +250 -0
  77. data/service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl +62 -0
  78. data/service/ssh/ext/ssh_core_rs/Cargo.lock +2345 -0
  79. data/service/ssh/ext/ssh_core_rs/Cargo.toml +30 -0
  80. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs +34 -0
  81. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd +40 -0
  82. data/service/ssh/ext/ssh_core_rs/src/channel.rs +296 -0
  83. data/service/ssh/ext/ssh_core_rs/src/coalesce.rs +143 -0
  84. data/service/ssh/ext/ssh_core_rs/src/codec.rs +71 -0
  85. data/service/ssh/ext/ssh_core_rs/src/conn.rs +628 -0
  86. data/service/ssh/ext/ssh_core_rs/src/gateway.rs +389 -0
  87. data/service/ssh/ext/ssh_core_rs/src/handler.rs +293 -0
  88. data/service/ssh/ext/ssh_core_rs/src/keepalive.rs +194 -0
  89. data/service/ssh/ext/ssh_core_rs/src/main.rs +351 -0
  90. data/service/ssh/ext/ssh_core_rs/src/portfwd.rs +378 -0
  91. data/service/ssh/ext/ssh_core_rs/src/proto.rs +198 -0
  92. data/service/ssh/ext/ssh_core_rs/src/sftp.rs +294 -0
  93. data/service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb +213 -0
  94. data/service/ssh/lib/network_infra_utility/ssh/client.rb +257 -0
  95. data/service/ssh/lib/network_infra_utility/ssh/config/schema.rb +90 -0
  96. data/service/ssh/lib/network_infra_utility/ssh/config/settings.rb +103 -0
  97. data/service/ssh/lib/network_infra_utility/ssh/config/store.rb +90 -0
  98. data/service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb +83 -0
  99. data/service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb +36 -0
  100. data/service/ssh/lib/network_infra_utility/ssh/ipc/router.rb +212 -0
  101. data/service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb +81 -0
  102. data/service/ssh/lib/network_infra_utility/ssh/security/host_key.rb +211 -0
  103. data/service/ssh/lib/network_infra_utility/ssh/security/vault.rb +211 -0
  104. data/service/ssh/lib/network_infra_utility/ssh/session/history.rb +56 -0
  105. data/service/ssh/lib/network_infra_utility/ssh/session/manager.rb +92 -0
  106. data/service/ssh/lib/network_infra_utility/ssh/session/session.rb +109 -0
  107. data/service/ssh/lib/network_infra_utility/ssh/session/tree.rb +95 -0
  108. data/service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb +435 -0
  109. data/service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb +78 -0
  110. data/service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb +159 -0
  111. data/service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb +195 -0
  112. data/service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb +212 -0
  113. data/service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb +127 -0
  114. data/service/ssh/lib/network_infra_utility/ssh/version.rb +7 -0
  115. data/service/ssh/lib/network_infra_utility/ssh.rb +44 -0
  116. data/support/basic/as_num.rb +221 -0
  117. data/support/basic/mac_address.rb +281 -0
  118. data/version.rb +1 -1
  119. metadata +138 -1
@@ -0,0 +1,250 @@
1
+ -module(ssh_sftp_session).
2
+ -behaviour(gen_server).
3
+
4
+ %% SFTP session — manages a single SFTP channel on an SSH connection.
5
+ %%
6
+ %% Key design (LLD §6.6):
7
+ %% - Each SFTP session is a gen_server, managed by ssh_sftp_sup
8
+ %% - Single session = serial operations (no concurrent ops on same channel)
9
+ %% - Concurrent transfers = multiple sftp_sessions on the same conn
10
+ %% - Connection close → sftp_sup cleans up all sessions for that conn_id
11
+
12
+ -export([
13
+ start_link/2,
14
+ conn_id/1,
15
+ get_id/1,
16
+ rpc_list_dir/1,
17
+ rpc_download/1,
18
+ rpc_upload/1,
19
+ rpc_mkdir/1,
20
+ rpc_remove/1,
21
+ rpc_stat/1
22
+ ]).
23
+ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
24
+
25
+ -include("ssh_ipc.hrl").
26
+ -include_lib("kernel/include/file.hrl").
27
+
28
+ %% ---------- Public API ----------
29
+
30
+ %% @doc Start an SFTP session on an existing SSH connection.
31
+ start_link(ConnId, SshRef) ->
32
+ gen_server:start_link(?MODULE, [ConnId, SshRef], []).
33
+
34
+ %% @doc Get the connection ID for this session.
35
+ conn_id(Pid) ->
36
+ gen_server:call(Pid, conn_id).
37
+
38
+ %% @doc Get the sftp_id for this session.
39
+ get_id(Pid) ->
40
+ gen_server:call(Pid, get_id).
41
+
42
+ %% @doc RPC handler for sftp.list_dir
43
+ rpc_list_dir(#{<<"sftp_id">> := SftpId, <<"path">> := Path}) ->
44
+ case find_by_sftp_id(SftpId) of
45
+ {ok, Pid} -> gen_server:call(Pid, {list_dir, Path});
46
+ {error, not_found} -> {error, sftp_not_found}
47
+ end.
48
+
49
+ %% @doc RPC handler for sftp.download
50
+ rpc_download(#{<<"sftp_id">> := SftpId, <<"remote">> := Remote, <<"local">> := Local}) ->
51
+ case find_by_sftp_id(SftpId) of
52
+ {ok, Pid} -> gen_server:call(Pid, {download, Remote, Local}, infinity);
53
+ {error, not_found} -> {error, sftp_not_found}
54
+ end.
55
+
56
+ %% @doc RPC handler for sftp.upload
57
+ rpc_upload(#{<<"sftp_id">> := SftpId, <<"local">> := Local, <<"remote">> := Remote}) ->
58
+ case find_by_sftp_id(SftpId) of
59
+ {ok, Pid} -> gen_server:call(Pid, {upload, Local, Remote}, infinity);
60
+ {error, not_found} -> {error, sftp_not_found}
61
+ end.
62
+
63
+ %% @doc RPC handler for sftp.mkdir
64
+ rpc_mkdir(#{<<"sftp_id">> := SftpId, <<"path">> := Path}) ->
65
+ case find_by_sftp_id(SftpId) of
66
+ {ok, Pid} -> gen_server:call(Pid, {mkdir, Path});
67
+ {error, not_found} -> {error, sftp_not_found}
68
+ end.
69
+
70
+ %% @doc RPC handler for sftp.remove
71
+ rpc_remove(#{<<"sftp_id">> := SftpId, <<"path">> := Path}) ->
72
+ case find_by_sftp_id(SftpId) of
73
+ {ok, Pid} -> gen_server:call(Pid, {remove, Path});
74
+ {error, not_found} -> {error, sftp_not_found}
75
+ end.
76
+
77
+ %% @doc RPC handler for sftp.stat
78
+ rpc_stat(#{<<"sftp_id">> := SftpId, <<"path">> := Path}) ->
79
+ case find_by_sftp_id(SftpId) of
80
+ {ok, Pid} -> gen_server:call(Pid, {stat, Path});
81
+ {error, not_found} -> {error, sftp_not_found}
82
+ end.
83
+
84
+ %% ---------- gen_server callbacks ----------
85
+
86
+ init([ConnId, SshRef]) ->
87
+ Id = ssh_codec:gen_sftp_id(ConnId),
88
+ case ssh_sftp:start_channel(SshRef, [{window, 10}, {packet, 32768}]) of
89
+ {ok, SftpPid} ->
90
+ {ok, #sftp{id = Id, conn_id = ConnId, ssh_ref = SshRef, sftp_pid = SftpPid}};
91
+ {error, Reason} ->
92
+ {stop, Reason}
93
+ end.
94
+
95
+ handle_call(conn_id, _From, #sftp{conn_id = ConnId} = S) ->
96
+ {reply, ConnId, S};
97
+
98
+ handle_call(get_id, _From, #sftp{id = Id} = S) ->
99
+ {reply, Id, S};
100
+
101
+ handle_call({list_dir, Path}, _From, #sftp{sftp_pid = P} = S) ->
102
+ case ssh_sftp:read_file_info_all(P, binary_to_list(Path)) of
103
+ {ok, Entries} ->
104
+ {reply, {ok, format_entries(Entries)}, S};
105
+ {error, E} ->
106
+ {reply, {error, E}, S}
107
+ end;
108
+
109
+ handle_call({download, Remote, Local}, _From, #sftp{sftp_pid = P} = S) ->
110
+ Result = do_download(P, binary_to_list(Remote), binary_to_list(Local), S),
111
+ {reply, Result, S};
112
+
113
+ handle_call({upload, Local, Remote}, _From, #sftp{sftp_pid = P} = S) ->
114
+ Result = do_upload(P, binary_to_list(Local), binary_to_list(Remote), S),
115
+ {reply, Result, S};
116
+
117
+ handle_call({mkdir, Path}, _From, #sftp{sftp_pid = P} = S) ->
118
+ Result = ssh_sftp:make_dir(P, binary_to_list(Path)),
119
+ {reply, Result, S};
120
+
121
+ handle_call({remove, Path}, _From, #sftp{sftp_pid = P} = S) ->
122
+ Result = ssh_sftp:delete(P, binary_to_list(Path)),
123
+ {reply, Result, S};
124
+
125
+ handle_call({stat, Path}, _From, #sftp{sftp_pid = P} = S) ->
126
+ case ssh_sftp:read_file_info(P, binary_to_list(Path)) of
127
+ {ok, #file_info{size = Size, mtime = Mtime, mode = Mode, type = Type}} ->
128
+ {reply, {ok, #{size => Size, mtime => Mtime, perms => Mode,
129
+ type => atom_to_binary(Type, utf8)}}, S};
130
+ {error, E} ->
131
+ {reply, {error, E}, S}
132
+ end;
133
+
134
+ handle_call(_Req, _From, S) ->
135
+ {reply, {error, not_implemented}, S}.
136
+
137
+ handle_cast(_Msg, S) ->
138
+ {noreply, S}.
139
+
140
+ handle_info(_Info, S) ->
141
+ {noreply, S}.
142
+
143
+ terminate(_Reason, #sftp{sftp_pid = P}) when is_pid(P) ->
144
+ _ = (catch ssh_sftp:stop_channel(P)),
145
+ ok;
146
+ terminate(_Reason, _S) ->
147
+ ok.
148
+
149
+ %% ---------- Internal ----------
150
+
151
+ %% @doc Format file_info entries for JSON response.
152
+ format_entries(Entries) ->
153
+ [format_entry(E) || E <- Entries].
154
+
155
+ format_entry({Name, #file_info{size = Size, mtime = Mtime, mode = Mode, type = Type}}) ->
156
+ #{
157
+ name => Name,
158
+ type => atom_to_binary(Type, utf8),
159
+ size => Size,
160
+ mtime => Mtime,
161
+ perms => Mode
162
+ }.
163
+
164
+ %% @doc Download a file from remote to local.
165
+ do_download(SftpPid, RemotePath, LocalPath, SftpState) ->
166
+ case ssh_sftp:read_file_info(SftpPid, RemotePath) of
167
+ {ok, #file_info{size = TotalSize, type = regular}} ->
168
+ case file:open(LocalPath, [write, binary]) of
169
+ {ok, LocalFile} ->
170
+ case ssh_sftp:open(SftpPid, RemotePath, [read, binary]) of
171
+ {ok, Handle} ->
172
+ Transferred = stream_download(SftpPid, Handle, LocalFile, 0, TotalSize, SftpState),
173
+ ssh_sftp:close(SftpPid, Handle),
174
+ file:close(LocalFile),
175
+ {ok, #{transferred => Transferred, total => TotalSize}};
176
+ {error, E} ->
177
+ file:close(LocalFile),
178
+ {error, E}
179
+ end;
180
+ {error, E} ->
181
+ {error, E}
182
+ end;
183
+ {error, E} ->
184
+ {error, E}
185
+ end.
186
+
187
+ stream_download(SftpPid, Handle, LocalFile, Transferred, Total, SftpState) ->
188
+ case ssh_sftp:read(SftpPid, Handle, 32768) of
189
+ {ok, Data} ->
190
+ ok = file:write(LocalFile, Data),
191
+ NewTransferred = Transferred + byte_size(Data),
192
+ push_progress(SftpState, NewTransferred, Total),
193
+ case byte_size(Data) < 32768 of
194
+ true -> NewTransferred;
195
+ false -> stream_download(SftpPid, Handle, LocalFile, NewTransferred, Total, SftpState)
196
+ end;
197
+ eof ->
198
+ Transferred
199
+ end.
200
+
201
+ %% @doc Upload a file from local to remote.
202
+ do_upload(SftpPid, LocalPath, RemotePath, SftpState) ->
203
+ case file:read_file_info(LocalPath) of
204
+ {ok, #file_info{size = TotalSize}} ->
205
+ case file:open(LocalPath, [read, binary]) of
206
+ {ok, LocalFile} ->
207
+ case ssh_sftp:open(SftpPid, RemotePath, [write, binary]) of
208
+ {ok, Handle} ->
209
+ Transferred = stream_upload(SftpPid, Handle, LocalFile, 0, TotalSize, SftpState),
210
+ ssh_sftp:close(SftpPid, Handle),
211
+ file:close(LocalFile),
212
+ {ok, #{transferred => Transferred, total => TotalSize}};
213
+ {error, E} ->
214
+ file:close(LocalFile),
215
+ {error, E}
216
+ end;
217
+ {error, E} ->
218
+ {error, E}
219
+ end;
220
+ {error, E} ->
221
+ {error, E}
222
+ end.
223
+
224
+ stream_upload(SftpPid, Handle, LocalFile, Transferred, Total, SftpState) ->
225
+ case file:read(LocalFile, 32768) of
226
+ {ok, Data} ->
227
+ ok = ssh_sftp:write(SftpPid, Handle, Data),
228
+ NewTransferred = Transferred + byte_size(Data),
229
+ push_progress(SftpState, NewTransferred, Total),
230
+ stream_upload(SftpPid, Handle, LocalFile, NewTransferred, Total, SftpState);
231
+ eof ->
232
+ Transferred
233
+ end.
234
+
235
+ %% @doc Push a transfer progress notification to Ruby.
236
+ push_progress(#sftp{id = Id}, Transferred, Total) ->
237
+ ssh_ipc_gateway:push_event(<<"sftp.progress">>, #{
238
+ <<"sftp_id">> => Id,
239
+ <<"transferred">> => Transferred,
240
+ <<"total">> => Total,
241
+ <<"speed">> => 0
242
+ }).
243
+
244
+ %% @doc Find an SFTP session by sftp_id.
245
+ find_by_sftp_id(SftpId) ->
246
+ case ets:lookup(sftp_index, SftpId) of
247
+ [{_, Pid}] -> {ok, Pid};
248
+ [] -> {error, not_found}
249
+ end.
250
+
@@ -0,0 +1,62 @@
1
+ -module(ssh_sftp_sup).
2
+ -behaviour(supervisor).
3
+
4
+ -export([start_link/0, start_child/2, list_for_conn/1, rpc_open/1]).
5
+ -export([init/1]).
6
+
7
+ %% @doc Start the SFTP session pool supervisor (simple_one_for_one).
8
+ start_link() ->
9
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
10
+
11
+ %% @doc Start a new SFTP session worker.
12
+ %% ConnId identifies the parent connection; SshRef is the ssh connection reference.
13
+ %% Returns {ok, SftpId} | {error, Reason}.
14
+ start_child(ConnId, SshRef) ->
15
+ case supervisor:start_child(?MODULE, [ConnId, SshRef]) of
16
+ {ok, Pid} ->
17
+ %% Retrieve the sftp_id generated by the session worker
18
+ SftpId = ssh_sftp_session:get_id(Pid),
19
+ ets:insert(sftp_index, {SftpId, Pid}),
20
+ {ok, SftpId};
21
+ {error, Reason} ->
22
+ {error, Reason}
23
+ end.
24
+
25
+ %% @doc List all SFTP sessions for a given connection.
26
+ list_for_conn(ConnId) ->
27
+ [Pid || {_, Pid, _, _} <- supervisor:which_children(?MODULE),
28
+ ssh_sftp_session:conn_id(Pid) =:= ConnId].
29
+
30
+ %% @doc RPC handler for sftp.open
31
+ rpc_open(#{<<"conn_id">> := ConnId}) ->
32
+ case find_conn_worker(ConnId) of
33
+ {ok, Pid} ->
34
+ SshRef = ssh_conn_worker:get_ssh_ref(Pid),
35
+ start_child(ConnId, SshRef);
36
+ {error, not_found} ->
37
+ {error, conn_not_found}
38
+ end.
39
+
40
+ %% @doc simple_one_for_one, intensity 20/60s, temporary workers.
41
+ init([]) ->
42
+ SupFlags = #{
43
+ strategy => simple_one_for_one,
44
+ intensity => 20,
45
+ period => 60
46
+ },
47
+ ChildSpec = #{
48
+ id => ssh_sftp_session,
49
+ start => {ssh_sftp_session, start_link, []},
50
+ restart => temporary,
51
+ shutdown => 5000,
52
+ type => worker,
53
+ modules => [ssh_sftp_session]
54
+ },
55
+ {ok, {SupFlags, [ChildSpec]}}.
56
+
57
+ find_conn_worker(ConnId) ->
58
+ case [Pid || Pid <- ssh_conn_sup:all_workers(),
59
+ ssh_conn_worker:conn_id(Pid) =:= ConnId] of
60
+ [Pid | _] -> {ok, Pid};
61
+ [] -> {error, not_found}
62
+ end.