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

NextPrevUpTopContentsIndex

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.

local-port

nil, a string or a fixnum.

ipv6

Ignored.

nodelay

A generalized boolean.

keepalive

A generalized boolean.

Values

stream

A socket-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 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 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 the 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, the 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 the verify argument:

(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

Socket streams with Java sockets and SSL on Android
open-tcp-stream


LispWorks User Guide and Reference Manual - 20 Sep 2017

NextPrevUpTopContentsIndex