One of
:input
,
:output
, or
:io
.
A positive number or
nil
.
A positive number or
nil
.
A keyword,
t
or
nil
, or a foreign pointer of type ssl-ctx-pointer or ssl-pointer.
One of the keywords
:client
,
:server
or
:both
. The default value is
:server
.
The
socket-stream
class implements a buffered stream connected to a socket. The socket handle, specified by
:socket
, and the direction, specified by
:direction
, must be passed for a meaningful stream to be constructed. Common Lisp input functions such as
read-char
will see
end-of-file
if the other end of the socket is closed.
The
:element-type
keyword determines the expected element type of the stream traffic. However, stream input and output functions for character and binary data generally work in the obvious way on a
socket-stream
with
element-type
base-char
,
(unsigned-byte 8)
or
(signed-byte 8)
. For example,
read-sequence
can be called with a string buffer and a binary
socket-stream
: the character data is constructed from the input as if by
code-char
. Similarly
write-sequence
can be called with a string buffer and a binary
socket-stream
: the output is converted from the character data as if by
char-code
. Also, 8-bit binary data can be read and written to a
base-char
socket-stream
.
All standard stream I/O functions except for
write-byte
and
read-byte
have this flexibility.
The
:read-timeout
initarg specifies the read timeout in seconds, or is
nil
, meaning there are no timeouts during reads (this is the default).
The
read-timeout
property is intended for use when a socket connection might hang during a call to any Common Lisp input function. The
read-timeout
can be set by make-instance or by open-tcp-stream. It can also be modified by
(setf stream:stream-read-timeout)
. When
read-timeout
is
nil
, there is no timeout during reads and the call may hang. When
read-timeout
is not
nil
, and there is no input from the socket for more than
read-timeout
seconds, any reading function returns
end-of-file
. The
read-timeout
does not limit the time inside
read
, but the time between successful extractions of data from the socket. Therefore, if the reading needs several rounds it may take longer than
read-timeout
.
Using
(setf stream:stream-read-timeout)
on the stream while it is inside a read function has undefined effects. However, the setf function can be used between calls to read functions. The
read-timeout
property of a stream can be read by
(stream:stream-read-timeout stream)
The
:write-timeout
initarg specifies the write timeout in seconds, or is
nil
, meaning that there are no timeouts during writes (this is the default).
The
write-timeout
property is similar to
read-timeout
, but for write operations. If flushing the stream buffer takes too long then
error
is called.
The keyword arguments
:ssl-ctx
,
:ssl-side
,
:ctx-configure-callback
and
:ssl-configure-callback
can be be passed to create and configure socket streams with SSL processing.
ssl-ctx
, if non-
nil
, specifies that the stream uses SSL and further specifies the
SSL_CTX
object to use. The value of
ssl-ctx
can be a symbol which, together with
ssl-side
, specifies which protocol to use. The value
t
or
:default
means use the default, which is currently the same as
:v23
. The values
:v2
,
:v3
,
:v23
and
:tls-v1
are mapped to the
SSLv2_*
,
SSLv3_*
,
SSLv23_*
and
TLSv1_*
methods respectively. With these symbol values of
ssl-ctx
, LispWorks makes a new
SSL_CTX
object and uses it and frees it when the stream is closed.
The value of
ssl-ctx
can also be a foreign pointer of type ssl-ctx-pointer (which corresponds to the C type
SSL_CTX*
). This is used and is not freed when the stream is closed. Also an SSL object is made and used, and this object is freed when the stream is closed. The foreign pointer may be a result of a call to make-ssl-ctx, but it can also a result of user code, provided that it points to a valid
SSL_CTX
and has the type ssl-ctx-pointer.
The value of
ssl-ctx
can also be a foreign pointer of type ssl-pointer (which corresponds to the C type
SSL*
). This specifies the SSL to use. This maybe a result of a call to ssl-new but can also be the result of user code, provided that it points to a valid SSL object and has the type ssl-pointer. The SSL is used and is not freed when the stream is closed.
When you pass a ssl-ctx-pointer or a ssl-pointer foreign pointer as the ssl-ctx argument, it must have already been set up correctly.
ssl-side specifies which side the socket stream is. The value of ssl-side is used in two cases:
SSL_CTX
object is created, it is used to select the method:
:client => *_client_method
:server => *_server_method
:both => *_method
:client
or
:server
, LispWorks calls
SSL_set_connect_state
or
SSL_set_accept_state
respectively.If the value of ssl-ctx is a ssl-pointer, ssl-side is ignored.
ctx-configure-callback
specifies a callback, a function which taks a foreign pointer of type ssl-ctx-pointer. This is called immediately after a new
SSL_CTX
is created. If the value of
ssl-ctx
is not a symbol,
ctx-configure-callback
is ignored.
ssl-configure-callback specifies a callback, a function which taks a foreign pointer of type ssl-pointer. This is called immediately after a new SSL is created. If the value of ssl-ctx is not a ssl-pointer, ssl-configure-callback is ignored.
The following makes a bidirectional stream connected to a socket specified by handle .
(make-instance 'comm:socket-stream
:socket handle
:direction :io
:element-type 'base-char)
This example creates a socket stream with a read-timeout:
(make-instance 'comm:socket-stream
:handle
handle
:direction :input
:read-timeout 42)
The following form illustrates character I/O in a binary
socket-stream
:
(with-open-stream (x
(comm:open-tcp-stream
"localhost" 80
:element-type '(unsigned-byte 8)))
(write-sequence (format nil "GET / HTTP/1.0~%~%") x)
(force-output x)
(let ((res (make-array 20 :element-type 'base-char)))
(values (read-sequence res x) res)))
The following form illustrates binary I/O in a
base-char
socket-stream
:
(with-open-stream (x
(comm:open-tcp-stream
"localhost" 80
:element-type 'base-char))
(write-sequence
(map '(simple-array (unsigned-byte 8) 1)
'char-code
(format nil "GET / HTTP/1.0~%~%"))
x)
(force-output x)
(let ((res (make-array 20
:element-type
'(unsigned-byte 8))))
(values (read-sequence res x)
(map 'string 'code-char res))))