public class LowLevelSocketImpl extends java.lang.Object implements LowLevelSocket
| Modifier and Type | Class and Description |
|---|---|
private static class |
LowLevelSocketImpl.ReadListener
This class is dedicated to listening for incoming socket data.
|
static class |
LowLevelSocketImpl.SocketData
A container holding the various client-socket data.
|
private static class |
LowLevelSocketImpl.StagedInput
Due to the nature of java sockets and how the 4GL sockets behave, all reading must be done
in a dedicated thread.
|
private static class |
LowLevelSocketImpl.WorkArea
Container for the context-local data.
|
| Modifier and Type | Field and Description |
|---|---|
private static ContextLocal<LowLevelSocketImpl.WorkArea> |
local
The context-local data of this class.
|
private static CentralLogger |
LOG
Logger
|
private static java.lang.Object |
modToken
Token used to authenticate with the dispatcher when registering APIs.
|
| Constructor and Description |
|---|
LowLevelSocketImpl(boolean local)
Create an instance and export its API to the network.
|
| Modifier and Type | Method and Description |
|---|---|
int |
connect(long resourceId,
java.lang.String host,
int port,
int timeout)
Establish a connection to the given host and port.
|
int |
connectSSL(long resourceId,
java.lang.String host,
int port,
java.lang.String serverName,
boolean nosessionreuse,
boolean nohostverify,
java.lang.String protocol,
int timeout)
Establish a SSL connection to the given host and port.
|
private static javax.net.ssl.SSLSocket |
createSslSocket(java.lang.String host,
int port,
java.lang.String serverName,
java.net.InetAddress inetAddress,
int localPort,
int timeout,
boolean nohostverify,
boolean errManager,
java.lang.String protocol)
Worker for creating a SSL socket and secure it according to specifications.
|
boolean |
disconnect(int id)
Disconnect this socket.
|
long |
getBytesAvailable(int id)
Get the available bytes to be read.
|
boolean |
getKeepAlive(int id)
Get the SO_KEEPALIVE option value for this socket.
|
java.lang.String |
getLocalHost(int id)
Get the IP address of this side of this connection.
|
int |
getLocalPort(int id)
Get the port number of this side of this connection.
|
int |
getReceiveBufferSize(int id)
Get the SO_RCVBUF option value for this socket.
|
java.lang.String |
getRemoteHost(int id)
Get the host IP address of the remote side of this connection.
|
int |
getRemotePort(int id)
Get the port number of the remote side of this connection.
|
boolean |
getReuseAddress(int id)
Get the SO_REUSEADDR option value for this socket.
|
int |
getSendBufferSize(int id)
Get the SO_SNDBUF option value for this socket.
|
int |
getSoLinger(int id)
Get the SO_LINGER option value for this socket.
|
int |
getSoTimeout(int id)
Get the SO_RCVTIMEO option value for this socket.
|
java.lang.String |
getSslServerName(int id)
In case of a SSL connection, get the digital certificate subject name of the server for
the current SSL session; else, return
null. |
boolean |
getTcpNoDelay(int id)
Get the TCP_NODELAY option value for this socket.
|
boolean |
isConnected(int id)
Check if the java socket is still connected.
|
private static boolean |
isReady(int id,
java.util.concurrent.CountDownLatch ready)
Wait until all socket-related threads are initialized.
|
private static LowLevelSocketImpl.SocketData |
locate(int id)
Identify the socket
socket data using the given ID. |
private static java.net.Socket |
locateSocket(int id)
Identify the associated
socket for the given ID. |
long |
read(int id,
memptr buffer,
long pos,
long len,
int mode)
Java implementation for the READ() SOCKET method, this will read the specified number of
bytes from the available data on the socket, and put it inside the memory buffer
argument at the specified position.
|
static LowLevelSocketImpl.SocketData |
registerClientSocket(java.net.Socket client,
boolean ssl)
When the server socket accepts a new connection, this will make sure the new socket is
registered and a
SocketImpl resource is also created on P2J server side. |
void |
setKeepAlive(int id,
boolean on)
Set the SO_KEEPALIVE option for this socket.
|
static void |
setNoHostVerify(boolean noHostVerify)
Sets value for the -nohostverify CONNECT arg.
|
void |
setReceiveBufferSize(int id,
int size)
Set the SO_RCVBUF value (the receive buffer size) for this socket.
|
void |
setReuseAddress(int id,
boolean on)
Set the SO_REUSEADDR option for this socket.
|
void |
setSendBufferSize(int id,
int size)
Set the SO_SNDBUF value (the send buffer size) for this socket.
|
void |
setSoLinger(int id,
boolean on,
int linger)
Set the SO_LINGER option for this socket.
|
void |
setSoTimeout(int id,
int timeout)
Set the SO_RCVTIMEO value (the number of seconds the socket waits to receive data before
timing out) for this socket.
|
void |
setTcpNoDelay(int id,
boolean on)
Set the TCP_NODELAY option for this socket.
|
long |
write(int id,
memptr buffer,
long pos,
long len)
Java implementation for the WRITE() SOCKET method, this will write data from the specified
buffer location (position and number of bytes) to the socket.
|
private static final CentralLogger LOG
private static java.lang.Object modToken
private static ContextLocal<LowLevelSocketImpl.WorkArea> local
LowLevelSocketImpl(boolean local)
local - true to register purely on a local basis (no remote/network access to these
methods).public static void setNoHostVerify(boolean noHostVerify)
noHostVerify - The value for the -nohostverify CONNECT argprivate static javax.net.ssl.SSLSocket createSslSocket(java.lang.String host,
int port,
java.lang.String serverName,
java.net.InetAddress inetAddress,
int localPort,
int timeout,
boolean nohostverify,
boolean errManager,
java.lang.String protocol)
throws java.io.IOException,
java.lang.SecurityException
Documentation states that OpenEdge keeps the public keys (certificates) as individual files
in a per-installation store (directory DLC/certs). We use per-client JKS storage
facilities in a unified trusted-cert.store in client installation. Certificates need
to be imported with java keytool:
keytool -import -alias a_server -file a_server.cer -keystore trusted-cert.store
The location of the store and password for access it can be passed-in at client startup as
bootstrap config value with the default value of trusted-cert.store in the current
directory.
Apparently OpenEdge's mkhashfile utility uses the rehashing function for creating
(not so) unique ids for each imported certificate. A similar (if not identical) feature is
offered by OpenSSL:
openssl x509 -in a_server.pem -noout -hash
host - The host name/IP to connect to.port - The port on the host.serverName - The server name indicator (SNI) set via -servername, for TLS connections.inetAddress - The local host name/IP to bind the socket to.localPort - The port on the local machine.timeout - Socket timeout (in milliseconds), or 0 if it never expires.nohostverify - If true, disables host verification for connection using HTTPS.errManager - Instruct how to handle encountered errors. If true ant exception is fed to
P2J ErrorManager, otherwise let the caller handle it using normal java
exceptions.protocol - The standard name of the requested protocol as defined by the SSLContext class.java.io.IOException - If any problems are encountered in the process.java.lang.SecurityExceptionpublic static LowLevelSocketImpl.SocketData registerClientSocket(java.net.Socket client, boolean ssl) throws java.io.IOException
SocketImpl resource is also created on P2J server side.client - The client socket.ssl - Flag indicating if this is a SSL connection.SocketImpl instance with the details of the new socket.java.io.IOException - If the socket's input or output streams couldn't be obtained.private static LowLevelSocketImpl.SocketData locate(int id)
socket data using the given ID.id - The ID of the associated socket on P2J Client side.private static java.net.Socket locateSocket(int id)
socket for the given ID.id - The ID of the associated socket on P2J Client side.private static boolean isReady(int id,
java.util.concurrent.CountDownLatch ready)
id - The socket ID on P2J client side.ready - The signal to wait on. If null, it returns true.true if all threads are initialized or ready is null;
false if someone interrupted the CountDownLatch.await()public int connect(long resourceId,
java.lang.String host,
int port,
int timeout)
throws java.io.IOException
connect in interface LowLevelSocketresourceId - The ID of the associated SocketImpl resource on server side.host - The IP address or name of the target host.port - The port number.timeout - connect timeoutjava.io.IOException - In case of errors while establishing the connection.public int connectSSL(long resourceId,
java.lang.String host,
int port,
java.lang.String serverName,
boolean nosessionreuse,
boolean nohostverify,
java.lang.String protocol,
int timeout)
throws java.io.IOException,
java.security.GeneralSecurityException
connectSSL in interface LowLevelSocketresourceId - The ID of the associated SocketImpl resource on server side.host - The IP address or name of the target host.port - The port number.serverName - The server name indicator (SNI) set via -servername, for TLS connections.nosessionreuse - Flag indicating that the ssl session ID must not be reused.nohostverify - Flag indicating that the target host name must not be validated against the
certificate's principal name.protocol - The standard name of the requested protocol as defined by the SSLContext class.timeout - connect timeoutjava.io.IOException - In case of errors while establishing the connection.java.security.GeneralSecurityException - In case of errors while establishing the SSL connection.public boolean isConnected(int id)
isConnected in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.true if the java socket is still connected.public boolean disconnect(int id)
disconnect in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.true if no errors were encountered during disconnect.public long getBytesAvailable(int id)
getBytesAvailable in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.public long read(int id,
memptr buffer,
long pos,
long len,
int mode)
throws java.io.IOException
Optionally the read mode can be set by the following values:
During READ processing, the read listener will be blocked from raising
new READ-RESPONSE events.
read in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.buffer - The memory buffer where read() puts the data.pos - The position in the memory buffer where the data is added.len - The number of bytes to read from the socket.mode - The mode to set for the reading operation.java.io.IOException - In case IO errors were encountered during read.public long write(int id,
memptr buffer,
long pos,
long len)
throws java.io.IOException
write in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.buffer - The memory buffer from which the data will be written to the socket.pos - The position in the memory buffer from where the data to be taken starts.len - The number of bytes to take from the memory buffer.java.io.IOException - In case IO errors were encoubtered during write.public java.lang.String getSslServerName(int id)
null.getSslServerName in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.public boolean getTcpNoDelay(int id)
throws java.net.SocketException
Socket.getTcpNoDelay() for more details.getTcpNoDelay in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public int getSoLinger(int id)
throws java.net.SocketException
Socket.getSoLinger() for more details.getSoLinger in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public boolean getKeepAlive(int id)
throws java.net.SocketException
Socket.getKeepAlive() for more details.getKeepAlive in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public boolean getReuseAddress(int id)
throws java.net.SocketException
Socket.getReuseAddress() for more details.getReuseAddress in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public int getReceiveBufferSize(int id)
throws java.net.SocketException
Socket.getReceiveBufferSize() for more details.getReceiveBufferSize in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public int getSendBufferSize(int id)
throws java.net.SocketException
Socket.getSendBufferSize() for more details.getSendBufferSize in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public int getSoTimeout(int id)
throws java.net.SocketException
Socket.getSoTimeout() for more details.getSoTimeout in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.java.net.SocketException - If the socket option could not be interrogated.public void setTcpNoDelay(int id,
boolean on)
throws java.net.SocketException
Socket.setTcpNoDelay(boolean) for more details.setTcpNoDelay in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.on - The TCP_NODELAY value.java.net.SocketException - If the socket option could not be set.public void setSoLinger(int id,
boolean on,
int linger)
throws java.net.SocketException
Socket.setSoLinger(boolean, int) for more details.setSoLinger in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.on - true to turn on the SO_LINGER option.linger - The linger time.java.net.SocketException - If the socket option could not be set.public void setKeepAlive(int id,
boolean on)
throws java.net.SocketException
Socket.setKeepAlive(boolean) for more details.setKeepAlive in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.on - The SO_KEEPALIVE value.java.net.SocketException - If the socket option could not be set.public void setReuseAddress(int id,
boolean on)
throws java.net.SocketException
Socket.setReuseAddress(boolean) for more details.setReuseAddress in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.on - The SO_REUSEADDR value.java.net.SocketException - If the socket option could not be set.public void setReceiveBufferSize(int id,
int size)
throws java.net.SocketException
Socket.setReceiveBufferSize(int) for more details.setReceiveBufferSize in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.size - The SO_RCVBUF value.java.net.SocketException - If the socket option could not be set.public void setSendBufferSize(int id,
int size)
throws java.net.SocketException
Socket.setSendBufferSize(int) for more details.setSendBufferSize in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.size - The SO_SNDBUF value.java.net.SocketException - If the socket option could not be set.public void setSoTimeout(int id,
int timeout)
throws java.net.SocketException
Socket.setSoTimeout(int) for more details.setSoTimeout in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.timeout - The SO_RCVTIMEO value.java.net.SocketException - If the socket option could not be set.public java.lang.String getLocalHost(int id)
getLocalHost in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.public int getLocalPort(int id)
getLocalPort in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.public java.lang.String getRemoteHost(int id)
getRemoteHost in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.public int getRemotePort(int id)
getRemotePort in interface LowLevelSocketid - The ID of the associated socket on P2J Client side.