-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
api-channels.texi
359 lines (285 loc) · 11.5 KB
/
api-channels.texi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
@c -*-texinfo-*-
@c This file is part of Guile-SSH Reference Manual.
@c Copyright (C) 2014-2021 Artyom V. Poptsov
@c See the file guile-ssh.texi for copying conditions.
@node Channels
@section Channels
@menu
* Channel Management::
* Port Forwarding::
@end menu
@c -----------------------------------------------------------------------------
@node Channel Management
@subsection Channel Management
@cindex data transferring
@tindex channel
The @code{(ssh channel)} module provides facilities to create
Guile-SSH channels and manipulating of them.
Channels are implemented as GNU Guile ports. Therefore they can be
used with regular I/O procedures such as @code{display}, @code{write},
@code{read-line} and friends (@pxref{Input and Output,,, guile, The
GNU Guile Reference Manual}). This section describes operations that
are specific for the channels.
When a channel is closed by the remote side, the local side detects it;
reading from such channel gives an EOF object when all data is read.
Note that when the parent session from which a channel is made is freed the
channel is freed as well.
@deffn {Scheme Procedure} channel? x
Return @code{#t} if @var{x} is a Guile-SSH channel, @code{#f}
otherwise.
@end deffn
@deffn {Scheme Procedure} make-channel session [mode]
Allocate a new Guile-SSH channel for the @var{session} (@pxref{Sessions}).
@var{flags} are determine what kind of a channel should be created. Possible
modes are: @code{OPEN_READ}, @code{OPEN_WRITE}, @code{OPEN_BOTH}. They allow
to create either an input channel, output channel or input/output channel
respectively.
@end deffn
@deffn {Scheme Procedure} channel-open-session channel
Open a session channel. This procedure actually turn the
@var{channel} into an open port available for I/O operations. Throw
@code{guile-ssh-error} on error. Return value is undefined.
@end deffn
@deffn {Scheme Procedure} channel-open? channel
Return @code{#t} if a @var{channel} is open, #f otherwise. Note that this procedure
also returns @code{#f} when the remote side is closed.
@end deffn
@deffn {Scheme Procedure} channel-request-exec channel command
@cindex non-interactive SSH session
@cindex command execution
Run a shell @var{command} without an interactive shell. The @var{channel}
must be open. Throw @code{guile-ssh-error} on error. Return value is
undefined.
This procedure is a low-level one and you should use remote pipes instead (@pxref{Remote Pipes}).
@strong{Note} that the procedure only can be used to execute a single command
on the remote host, so you should close the channel after
@code{channel-request-exec}. If you want to execute another command then you
must open a new channel and use it.
Example:
@lisp
(let ((channel (make-channel session)))
(channel-open-session channel)
(channel-request-exec channel "uname")
(read-line channel))
@result{} "Linux"
@end lisp
@end deffn
@deffn {Scheme Procedure} channel-request-pty channel
Request a @acronym{PTY} (pseudo terminal). Throw @code{guile-ssh-error} on
error. The @var{channel} must be open. Return value is undefined.
@end deffn
@deffn {Scheme Procedure} channel-request-shell channel
Request a shell. The @var{channel} must be open. Throw
@code{guile-ssh-error} on error. Return value is undefined.
@end deffn
@deffn {Scheme Procedure} channel-request-env channel variable value
@cindex setting of environment variables
Set an environment @var{variable} to @var{value}. Throw
@code{guile-ssh-error} on error. The @var{channel} must be open. Return
value is undefined.
@end deffn
@deffn {Scheme Procedure} channel-request-send-exit-status channel exit-status
Send an @var{exit-status} to the remote process (as described in RFC 4254,
section 6.10). Only SSH-v2 is supported. Return value is undefined.
The @var{channel} needs to be closed with after this message.
@end deffn
@deffn {Scheme Procedure} channel-set-pty-size! channel columns rows
Change size of the @acronym{PTY} to @var{columns} and @var{rows}. The
@var{channel} must be open. Return value is undefined.
@end deffn
@deffn {Scheme Procedure} channel-set-stream! channel stream
Set default @var{stream} for @var{channel}. @var{stream} must be one of the
following symbols: @code{stdout} (default), @code{stderr}. The @var{channel}
must be open. Throw @code{guile-ssh-error} on error. Return value is
undefined.
Example:
@lisp
(channel-set-stream! channel 'stderr)
@end lisp
@end deffn
@deffn {Scheme Procedure} channel-get-stream channel
Get current stream name from @var{channel}. The @var{channel} must be open.
Throw @code{guile-ssh-error} on error. Return one of the following symbols:
@code{stdout}, @code{stderr}.
Example:
@lisp
(channel-get-stream channel)
@result{} 'stderr
@end lisp
@end deffn
@deffn {Scheme Procedure} channel-get-session channel
Get the session to which belongs the @var{channel}. Throw
@code{guile-ssh-error} on an error. Return the session.
@end deffn
@deffn {Scheme Procedure} channel-send-eof channel
Send an end of file (EOF) on the @var{channel}. This action doesn't close the
@var{channel}; you may still read from it but not write. Throw
@code{guile-ssh-error} on an error. Return value is undefined.
Example:
@lisp
(use-modules (ice-9 rdelim)
;; Guile-SSH modules.
(ssh auth)
(ssh popen)
(ssh session)
(ssh channel))
;; Make a session
(define s (make-session #:host "example.org"))
;; Connect to the server
(connect! s)
;; Authenticate
(userauth-agent! s)
;; Open a remote pipe to 'wc' command running on
;; the server.
(let ((p (open-remote-pipe s "wc" OPEN_BOTH)))
;; Send data to 'wc' command using the remote pipe.
(display "Hello Scheme World!" p)
;; 'wc' reads data until EOF and writes its result
;; afterwards.
(channel-send-eof p)
;; Read the 'wc' output.
(read-line p))
@result{} " 0 3 19"
@end lisp
@end deffn
@deffn {Scheme Procedure} channel-eof? channel
Return @code{#t} if remote has sent @acronym{EOF}, @code{#f} otherwise. Throw
@code{guile-ssh-error} if the channel has been closed and freed.
@end deffn
@deffn {Scheme Procedure} channel-get-exit-status channel
Get the exit status of the @var{channel} (error code from the executed
instruction). The @var{channel} must be open. Return the exist status, or
@code{#f} if no exit status has been returned (yet). Throw
@code{guile-ssh-error} on error.
@end deffn
@c -----------------------------------------------------------------------------
@node Port Forwarding
@subsection Port Forwarding
@cindex Port forwarding
Low-level API from @code{(ssh channel)} module to manage SSH port
forwarding. These procedures @strong{do not} bind the ports and do not
automatically forward the content of a socket to the channel. You should
either implement binding and data forwarding in your application or use the
tunnel API (@pxref{Tunnels, Guile-SSH tunnel API})
@deffn {Scheme Procedure} channel-open-forward channel [#:source-host=''localhost''] #:local-port #:remote-host [#:remote-port=local-port]
Open a (local) TCP/IP forwarding @var{channel}. Connect to a
@var{remote-host} and @var{remote-port}, and use @var{source-host} and
@var{local-port} as origination of connections.
The procedure returns one of the following symbols:
@table @samp
@item ok
Success.
@item again
We are in the nonblocking mode and the call to be done again.
@item error
An error occurred.
@end table
The local port forwarding works as follows:
@example
local-host remote-host
,..............., ,.................
: : : :
: [a browser] : : [a web server] :
: | : : A :
: | : : | :
: port 8080 : : port 80 :
: | : : | :
: V : : | :
: [SSH client]===========>[SSH server] :
: : : :
'...............' '................'
@end example
Where port 8080 is an arbitrary @var{local-port} and port 80 is a
@var{remote-port}.
Also in our case, ``SSH client'' is an application that uses Guile-SSH and
calls @code{channel-open-forward}.
Example:
@lisp
(channel-open-forward channel
#:local-port 8080
#:remote-host "www.example.org"
#:remote-port 80)
@end lisp
@end deffn
@deffn {Scheme Procedure} channel-listen-forward session [#:address=#f] [#:port=0]
Start a TCP/IP reverse (remote) port forwarding. Send the ``tcpip-forward''
global request using @var{session} to ask the server to begin listening for
inbound connections on the specified @var{address} and @var{port}.
If @var{address} is not specified (or set to @code{#f}) then the server binds
all addresses on all protocol families supported by the server. When 0 is
passed as a @var{port} then server allocates the next unprivileged port.
The procedure returns two values: the first value is the result of the
operation, and the second value is the bound port number; if @var{port} was
set to 0 then the procedure returns the chosen port number.
The result of the operation can be one of the following symbols:
@table @samp
@item ok
Success.
@item again
We are in the nonblocking mode and the call to be done again.
@item error
An error occurred.
@end table
Reverse port forwarding looks as follows:
@example
local-host remote-host
,................, ,.................
: : : :
: [a web server] : : [a browser] :
: A : : | :
: | : : | :
: port 80 : : port 8080 :
: | : : | :
: | : : V :
: [SSH client]<===========[SSH server] :
: : : :
'................' '................'
@end example
@end deffn
@deffn {Scheme Procedure} channel-accept-forward session [timeout=0]
Accept an incoming TCP/IP forwarding channel and get information about
incoming connection. Return two values: the first value is the incoming
channel, and the second value is a port number on which the connection was
issued.
@end deffn
@deffn {Scheme Procedure} channel-cancel-forward session address port
Send ``cancel-tcpip-forward'' global request to @var{session} to ask the
server to cancel a ``tcpip-forward'' request on the bound @var{address} and
@var{port}.
The result of the operation can be one of the following symbols:
@table @samp
@item ok
Success.
@item again
We are in the nonblocking mode and the call to be done again.
@item error
An error occurred.
@end table
Here's an example Guile program that uses @code{channel-cancel-forward} to
cancel reverse port forwarding on a server:
@lisp
#!/usr/bin/guile \
-e main
!#
(use-modules (ssh session)
(ssh auth)
(ssh channel))
(define (main args)
(let ((session (make-session #:user "alice"
#:host "127.0.0.1"
#:port 22
#:log-verbosity 'rare)))
(connect! session)
(userauth-agent! session)
;; Send "tcpip-forward" request to an SSH server
(channel-listen-forward session #:address "localhost" #:port 12345)
;; Accept incoming reverse port forwarding requests with
;; 'channel-accept-forward' in some kind of loop...
;; Cancel the issued "tcpip-forward" request with
;; "cancel-tcpip-forward" request
(channel-cancel-forward session "localhost" 12345)))
@end lisp
@end deffn
@c Local Variables:
@c TeX-master: "guile-ssh.texi"
@c End: