All Manuals > LispWorks® User Guide and Reference Manual > 32 The COMM Package

open-tcp-stream-using-java Function

Summary

Open a TCP stream using Java sockets for communication.

Package

comm

Signature

open-tcp-stream-using-java hostspec service &key factory verify direction element-type errorp read-timeout write-timeout timeout ssl-ctx ctx-configure-callback ssl-configure-callback tlsext-host-name local-address ipv6 local-port nodelay keepalive => stream

Arguments
hostspec
An integer or string or an ipv6-address object.
service
A string or a fixnum.
factory
A Java socket factory.
verify
t, nil, :strict, :browser-compat, a string or a jobject.
direction
One of :input, :output or :io.
element-type
base-char or a subtype of integer.
errorp
A boolean.
read-timeout
A positive number, or nil.
write-timeout
Ignored.
timeout
A positive number, or nil.
ssl-ctx
A generalized boolean.
ctx-configure-callback
Ignored.
ssl-configure-callback
Ignored.
tlsext-host-name
Ignored.
local-address
nil, an integer, a string or a ipv6-address object.
ipv6
Ignored.
local-port
nil, a string or a fixnum.
nodelay
A generalized boolean.
keepalive
A generalized boolean.
Values
stream
Description

The function open-tcp-stream-using-java opens a TCP stream using Java sockets for communication.

Note: open-tcp-stream-using-java does not have any clear advantage over open-tcp-stream. Use it only when you really need it.

open-tcp-stream-using-java accepts the same service, direction, element-type, errorp, read-timeout, timeout, local-address, local-port, nodelay and keepalive arguments as open-tcp-stream, plus factory and verify, but ignores the values of write-timeout, ipv6, ctx-configure-callback, ssl-configure-callback and tlsext-host-name. It also treats ssl-ctx as a generalized boolean, where any non-nil value means using SSL Java object.

open-tcp-stream-using-java opens and returns a socket-stream like open-tcp-stream, but the socket object that it uses is a Java object. However, cl:listen is unreliable on such streams, and they cannot be used in wait-for-input-streams. See 25.9 Socket streams with Java sockets and SSL on Android for details.

The keyword argument factory can be used to specify the socket factory to use to create the Java socket. When passed, it must be a Java socket factory, that is a jobject which is an instance of class javax.net.SocketFactory. In this case the socket is generated from this factory, the factory determines whether it is a SSL socket or not, and the value of ssl-ctx is used only to decide whether to do a handshake. By default, the default factory (the result of "getDefault") of javax.net.SocketFactory (when ssl-ctx is nil) or javax.net.ssl.SSLSocketFactory (when ssl-ctx is non-nil) is used.

The keyword argument verify is used only when ssl-ctx is non-nil. It controls verification of hostspec when SSL is used, which means checking that the certificate that was returned by the server is for this server. The default value t means using SSLCertificateSocketFactory on Android when factory is not supplied (see below), on other platforms it is the same as :strict. :strict mean uses the strict verifier (Java class org.apache.http.conn.ssl.StrictHostnameVerifier). :browser-compat means using "browser compatible" verifier (Java class org.apache.http.conn.ssl.BrowserCompatHostnameVerifier). Verification with :browser-compat is a little more relaxed than with :strict.

On Android when verify is t and factory is nil, the code uses the socket factory android.net.SSLCertificateSocketFactory (instead of the default of javax.net.ssl.SSLSocketFactory), which is doing the verification itself. When factory is non-nil, Android does the same as in the previous paragraph (verify using the strict verifier). The SSLCertificateSocketFactory has the advantage that it uses SNI (Server Name Indication), which makes verification work better.

When verify is a string, it has to be the hostname to use for verification, instead of hostspec argument. The verification is done using the strict verifier.

When verify is a jobject, it must be a verifier (of class javax.net.ssl.HostnameVerifier), and it is used as-is.

The verifier classes above are part of httpclient from apache.org, and therefore to use them (which is the default when using SSL), you need to have httpclient. On Android it is always available, so it is not an issue, on another architectures it needs to be added to the class path.

When verify is nil, hostspec is not verified, which is not recommended. However, there are valid sites which will fail verification, because they return a certificate for the wrong site (that happens due to use of virtual hosts). At the time of writing, "gmail.com" is one of them, and returns a certificate for "mail.google.com". However, if the client uses SNI, which is used by Java socket in Java 1.7 or higher, this server does return the correct certificate, and in general all servers should work when using SNI. On Android the default setting uses the SSLCertificateSocketFactory (discussed above), which is using SNI. Thus there is a problem only when using Java 1.6 or earlier, and for Android only when you use your own factory. For these cases, you can either use verify nil, or pass the name in the certificate as verify:

(comm:open-tcp-stream-using-java "gmail.com" 443
                                 :ssl-ctx t
                                 :verify "mail.google.com")

Note however that this will fail if SNI is used.

Notes
  1. The Java virtual machine (JVM) must be running for open-tcp-stream-using-java to work. On Android the JVM always runs, on other architectures it needs to have been started by init-java-interface. When using ssl-ctx, httpclient must be available too, and again it is always available on Android.
  2. On Android, or if you call switch-open-tcp-stream-with-ssl-to-java, open-tcp-stream uses Java objects for SSL streams. The result of open-tcp-stream and open-tcp-stream-using-java with ssl-ctx non-nil is identical in this case.
  3. Using Java sockets was added mainly for SSL streams on Android. It may be useful in other circumstances.
  4. You can also make a socket-stream with a Java socket by passing the Java socket that your code has created to (make-instance 'socket-stream ...). Note that closing such a stream will close the socket, and if you want to avoid that you need to use replace-socket-stream-socket.
See also

25.9 Socket streams with Java sockets and SSL on Android
open-tcp-stream
25 TCP and UDP socket communication and SSL


LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:26