Package org.ldaptive.transport.netty
Class NettyConnection
- java.lang.Object
-
- org.ldaptive.transport.TransportConnection
-
- org.ldaptive.transport.netty.NettyConnection
-
- All Implemented Interfaces:
AutoCloseable,Connection
final class NettyConnection extends TransportConnection
Netty based connection implementation.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static classNettyConnection.AddRemoveHandlerInvokes a latch when this handler is added or removed from a pipeline.protected static classNettyConnection.AutoReadEventHandlerInitiates a channel read when an LDAP message has been processed and auto read is false.classNettyConnection.BindOperationHandleBind specific operation handle that locks other operations until the bind completes.private classNettyConnection.ClientInitializerSets up the Netty pipeline for this connection.private classNettyConnection.CloseFutureListenerListener for channel close events.private classNettyConnection.InboundExceptionHandlerSetsinboundExceptionand closes the channel when an exception occurs.private classNettyConnection.InboundMessageHandlerMatches an inbound LDAP response message to its operation handle and removes that handle from the response queue.private classNettyConnection.LogFutureListenerListener that logs the future success state when it occurs.protected static classNettyConnection.MessageDecoderDecodes byte buffer into a concrete LDAP response message.protected static classNettyConnection.MessageStatusEnum that describes the state of an LDAP message in the pipeline.protected static classNettyConnection.RequestEncoderEncodes an LDAP request into its DER bytes.private classNettyConnection.ValidatorHandlerSchedules a connection validator to run based on its strategy.
-
Field Summary
Fields Modifier and Type Field Description private ReentrantReadWriteLockbindLockOperation lock when a bind occurs.private io.netty.channel.ChannelchannelConnection to the LDAP server.private Map<io.netty.channel.ChannelOption,Object>channelOptionsNetty channel configuration options.private Class<? extends io.netty.channel.Channel>channelTypeType of channel.private NettyConnection.CloseFutureListenercloseListenerListener notified when the connection is closed.private ExecutorServiceconnectionExecutorExecutor for scheduling various connection related tasks that cannot or should not be handled by the netty event loop groups.private InstantconnectTimeTime this connection was successfully established, null if the connection is not open.private ThrowableinboundExceptionLast exception received on the inbound pipeline.private io.netty.channel.EventLoopGroupioWorkerGroupEvent worker group used to process I/O.private LdapURLldapURLURL derived from the connection strategy.private static LoggerLOGGERLogger for this class.private AtomicIntegermessageIDMessage ID counter, incremented as requests are sent.private io.netty.channel.EventLoopGroupmessageWorkerGroupEvent worker group used to process inbound messages.private HandleMappendingResponsesQueue holding requests that haven't received a response.private static NettyConnection.AutoReadEventHandlerREAD_NEXT_MESSAGEInbound handler to read the next message if autoRead is false.private ReentrantReadWriteLockreconnectLockBlock operations while a reconnect is occurring.private static NettyConnection.RequestEncoderREQUEST_ENCODERRequest encoder pipeline handler.private booleanshutdownOnCloseWhether to shutdown the event loop groups onConnection.close().-
Fields inherited from class org.ldaptive.transport.TransportConnection
closeLock, connectionConfig, lastSuccessfulOpen, openLock
-
-
Constructor Summary
Constructors Constructor Description NettyConnection(ConnectionConfig config, Class<? extends io.netty.channel.Channel> type, io.netty.channel.EventLoopGroup ioGroup, io.netty.channel.EventLoopGroup messageGroup, boolean shutdownGroups)Creates a new connection.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidclose(RequestControl... controls)Closes this connection.protected voidcomplete(DefaultOperationHandle<?,?> handle)Report that the supplied handle has completed.private io.netty.channel.ChannelFutureconnectBootstrap(NettyConnection.ClientInitializer initializer)Creates a new bootstrap with the supplied initializer and uses that bootstrap to connect to the ldapURL.private io.netty.channel.ChannelconnectInternal()Creates a Netty bootstrap and connects to the LDAP server.private ObjectconvertChannelOption(String value)Performs a best effort at converting a channel option value to the correct type.private io.netty.bootstrap.BootstrapcreateBootstrap(NettyConnection.ClientInitializer initializer)Creates a NettyBootstrapwith the supplied client initializer.private NettyConnection.ClientInitializercreateClientInitializer()Creates a new client initializer.private io.netty.handler.ssl.SslHandlercreateSslHandler(ConnectionConfig config)Creates a Netty SSL handler using the supplied connection config.(package private) intgetAndIncrementMessageID()Returns the value of the next message ID and increments the counter.(package private) Map<io.netty.channel.ChannelOption,Object>getChannelOptions()Returns the channel options.(package private) io.netty.channel.EventLoopGroupgetIoWorkerGroup()Returns the I/O worker group.LdapURLgetLdapURL()Returns the URL that was selected for this connection.(package private) intgetMessageID()Returns the value of the next message ID.(package private) io.netty.channel.EventLoopGroupgetMessageWorkerGroup()Returns the message worker group.private booleanisClosing()Returns whether this connection is currently attempting to close.booleanisOpen()Returns whether the underlying Netty channel is open.private booleanisOpening()Returns whether this connection is currently attempting to open.private voidnotifyOperationHandlesOfClose()Sends an exception notification to all pending responses that the connection has been closed.protected voidopen(LdapURL url)Attempt to open a connection to the supplied LDAP URL.private voidopenInitialize(LdapURL url)Initializes this connection for use after it has been established.voidoperation(AbandonRequest request)Executes an abandon operation.DefaultOperationHandle<AddRequest,AddResponse>operation(AddRequest request)Creates a handle for an add operation.NettyConnection.BindOperationHandleoperation(BindRequest request)Creates a handle for a bind operation.DefaultCompareOperationHandleoperation(CompareRequest request)Creates a handle for a compare operation.DefaultOperationHandle<DeleteRequest,DeleteResponse>operation(DeleteRequest request)Creates a handle for a delete operation.DefaultExtendedOperationHandleoperation(ExtendedRequest request)Creates a handle for an extended operation.(package private) Resultoperation(StartTLSRequest request)Performs a startTLS operation.DefaultOperationHandle<ModifyDnRequest,ModifyDnResponse>operation(ModifyDnRequest request)Creates a handle for a modify dn operation.DefaultOperationHandle<ModifyRequest,ModifyResponse>operation(ModifyRequest request)Creates a handle for a modify operation.BindResponseoperation(DefaultSaslClientRequest request)Performs a SASL client bind operation.BindResponseoperation(SaslClientRequest request)Performs a SASL bind operation that uses a custom client.DefaultSearchOperationHandleoperation(SearchRequest request)Creates a handle for a search operation.protected voidoperation(UnbindRequest request)Executes an unbind operation.private voidreconnect()Attempts to reestablish the channel for this connection.(package private) voidsetMessageID(int i)Sets the value of the next message ID.protected booleantest(LdapURL url)Determine whether the supplied URL is acceptable for use.private voidthrowIfClosed()Throws an exception if the Netty channel is closed.StringtoString()private voidwaitForConnectionEstablish(NettyConnection.ClientInitializer initializer, io.netty.channel.ChannelFuture future)Waits until the TCP connection has completed.private voidwaitForSSLHandshake(io.netty.channel.Channel ch)Waits until the SSL handshake has completed.protected voidwrite(DefaultOperationHandle<?,?> handle)Write the request in the supplied handle to the LDAP server.-
Methods inherited from class org.ldaptive.transport.TransportConnection
open, reopen, strategyOpen
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
-
Methods inherited from interface org.ldaptive.Connection
close
-
-
-
-
Field Detail
-
LOGGER
private static final Logger LOGGER
Logger for this class.
-
REQUEST_ENCODER
private static final NettyConnection.RequestEncoder REQUEST_ENCODER
Request encoder pipeline handler.
-
READ_NEXT_MESSAGE
private static final NettyConnection.AutoReadEventHandler READ_NEXT_MESSAGE
Inbound handler to read the next message if autoRead is false.
-
channelType
private final Class<? extends io.netty.channel.Channel> channelType
Type of channel.
-
ioWorkerGroup
private final io.netty.channel.EventLoopGroup ioWorkerGroup
Event worker group used to process I/O.
-
messageWorkerGroup
private final io.netty.channel.EventLoopGroup messageWorkerGroup
Event worker group used to process inbound messages.
-
shutdownOnClose
private final boolean shutdownOnClose
Whether to shutdown the event loop groups onConnection.close().
-
channelOptions
private final Map<io.netty.channel.ChannelOption,Object> channelOptions
Netty channel configuration options.
-
pendingResponses
private final HandleMap pendingResponses
Queue holding requests that haven't received a response.
-
closeListener
private final NettyConnection.CloseFutureListener closeListener
Listener notified when the connection is closed.
-
messageID
private final AtomicInteger messageID
Message ID counter, incremented as requests are sent.
-
reconnectLock
private final ReentrantReadWriteLock reconnectLock
Block operations while a reconnect is occurring.
-
bindLock
private final ReentrantReadWriteLock bindLock
Operation lock when a bind occurs.
-
connectionExecutor
private ExecutorService connectionExecutor
Executor for scheduling various connection related tasks that cannot or should not be handled by the netty event loop groups. Reconnects in particular require a dedicated thread as the event loop group may be shared or may not be configured with enough threads to handle the task.
-
ldapURL
private LdapURL ldapURL
URL derived from the connection strategy.
-
channel
private io.netty.channel.Channel channel
Connection to the LDAP server.
-
connectTime
private Instant connectTime
Time this connection was successfully established, null if the connection is not open.
-
inboundException
private Throwable inboundException
Last exception received on the inbound pipeline.
-
-
Constructor Detail
-
NettyConnection
NettyConnection(ConnectionConfig config, Class<? extends io.netty.channel.Channel> type, io.netty.channel.EventLoopGroup ioGroup, io.netty.channel.EventLoopGroup messageGroup, boolean shutdownGroups)
Creates a new connection. Netty supports various transport implementations including NIO, EPOLL, KQueue, etc. The class type and event loop group are tightly coupled in this regard.- Parameters:
config- connection configurationtype- type of channelioGroup- event loop group that handles I/O and supports the channel type, cannot be nullmessageGroup- event loop group that handles inbound messages, can be nullshutdownGroups- whether to shutdown the event loop groups when the connection is closed
-
-
Method Detail
-
convertChannelOption
private Object convertChannelOption(String value)
Performs a best effort at converting a channel option value to the correct type. Handles Boolean and Integer types.- Parameters:
value- to convert- Returns:
- converted value or the supplied value if no conversion occurred
-
createBootstrap
private io.netty.bootstrap.Bootstrap createBootstrap(NettyConnection.ClientInitializer initializer)
Creates a NettyBootstrapwith the supplied client initializer.- Parameters:
initializer- to provide to the bootstrap- Returns:
- Netty bootstrap
-
test
protected boolean test(LdapURL url)
Description copied from class:TransportConnectionDetermine whether the supplied URL is acceptable for use.- Specified by:
testin classTransportConnection- Parameters:
url- LDAP URL to test- Returns:
- whether URL can be become active
-
open
protected void open(LdapURL url) throws LdapException
Description copied from class:TransportConnectionAttempt to open a connection to the supplied LDAP URL.- Specified by:
openin classTransportConnection- Parameters:
url- LDAP URL to connect to- Throws:
LdapException- if opening the connection fails
-
openInitialize
private void openInitialize(LdapURL url) throws LdapException
Initializes this connection for use after it has been established. If startTLS is configured it will be performed. Any configured connection initializers are invoked.- Parameters:
url- LDAP URL to connect to- Throws:
LdapException- if initializing the connection fails
-
getLdapURL
public LdapURL getLdapURL()
Description copied from interface:ConnectionReturns the URL that was selected for this connection. The existence of this value does not indicate a current established connection.- Returns:
- LDAP URL
-
connectInternal
private io.netty.channel.Channel connectInternal() throws ConnectExceptionCreates a Netty bootstrap and connects to the LDAP server. Handles the details of adding an SSL handler to the pipeline. This method waits until the connection is established.- Returns:
- channel for the established connection.
- Throws:
ConnectException- if the connection fails
-
createClientInitializer
private NettyConnection.ClientInitializer createClientInitializer() throws ConnectException
Creates a new client initializer. If theldapURLis LDAPS an SSL handler is added to the client initializer.- Returns:
- client initializer
- Throws:
ConnectException- if the SSL engine cannot be initialized
-
createSslHandler
private io.netty.handler.ssl.SslHandler createSslHandler(ConnectionConfig config) throws SSLException
Creates a Netty SSL handler using the supplied connection config.- Parameters:
config- containing SSL config- Returns:
- SSL handler
- Throws:
SSLException- if the SSL engine cannot be initialized
-
connectBootstrap
private io.netty.channel.ChannelFuture connectBootstrap(NettyConnection.ClientInitializer initializer)
Creates a new bootstrap with the supplied initializer and uses that bootstrap to connect to the ldapURL.- Parameters:
initializer- to create bootstrap with- Returns:
- channel future produced from the connect invocation
-
waitForConnectionEstablish
private void waitForConnectionEstablish(NettyConnection.ClientInitializer initializer, io.netty.channel.ChannelFuture future) throws ConnectException
Waits until the TCP connection has completed.- Parameters:
initializer- used to determine whether to wait for the SSL handshake to completefuture- to wait on- Throws:
ConnectException- if the connection fails
-
waitForSSLHandshake
private void waitForSSLHandshake(io.netty.channel.Channel ch) throws SSLExceptionWaits until the SSL handshake has completed.- Parameters:
ch- that the handshake is occurring on- Throws:
SSLException- if the handshake fails
-
operation
Result operation(StartTLSRequest request) throws LdapException
Performs a startTLS operation. This method can only be invoked when a connection is opened.- Parameters:
request- to send- Returns:
- result of the startTLS operation
- Throws:
LdapException- if the operation fails
-
operation
protected void operation(UnbindRequest request)
Description copied from class:TransportConnectionExecutes an unbind operation. Clients should close connections usingConnection.close().- Specified by:
operationin classTransportConnection- Parameters:
request- unbind request
-
operation
public BindResponse operation(SaslClientRequest request) throws LdapException
Performs a SASL bind operation that uses a custom client.- Parameters:
request- to send- Returns:
- result of the GSS-API bind operation
- Throws:
LdapException- if the operation fails or another bind is in progress
-
operation
public BindResponse operation(DefaultSaslClientRequest request) throws LdapException
Performs a SASL client bind operation.- Parameters:
request- to send- Returns:
- result of the SASL client bind operation
- Throws:
LdapException- if the operation fails or another bind is in progress
-
operation
public void operation(AbandonRequest request)
Description copied from interface:ConnectionExecutes an abandon operation. Clients should execute abandons usingOperationHandle.abandon().- Parameters:
request- abandon request
-
operation
public DefaultOperationHandle<AddRequest,AddResponse> operation(AddRequest request)
Description copied from interface:ConnectionCreates a handle for an add operation.- Parameters:
request- add request- Returns:
- operation handle
-
operation
public NettyConnection.BindOperationHandle operation(BindRequest request)
Description copied from interface:ConnectionCreates a handle for a bind operation. Since clients must not send requests while a bind is in progress, some methods may not be supported on the operation handle.- Parameters:
request- bind request- Returns:
- operation handle
-
operation
public DefaultCompareOperationHandle operation(CompareRequest request)
Description copied from interface:ConnectionCreates a handle for a compare operation.- Parameters:
request- compare request- Returns:
- compare operation handle
-
operation
public DefaultOperationHandle<DeleteRequest,DeleteResponse> operation(DeleteRequest request)
Description copied from interface:ConnectionCreates a handle for a delete operation.- Parameters:
request- delete request- Returns:
- operation handle
-
operation
public DefaultExtendedOperationHandle operation(ExtendedRequest request)
Description copied from interface:ConnectionCreates a handle for an extended operation.- Parameters:
request- extended request- Returns:
- extended operation handle
-
operation
public DefaultOperationHandle<ModifyRequest,ModifyResponse> operation(ModifyRequest request)
Description copied from interface:ConnectionCreates a handle for a modify operation.- Parameters:
request- modify request- Returns:
- operation handle
-
operation
public DefaultOperationHandle<ModifyDnRequest,ModifyDnResponse> operation(ModifyDnRequest request)
Description copied from interface:ConnectionCreates a handle for a modify dn operation.- Parameters:
request- modify dn request- Returns:
- operation handle
-
operation
public DefaultSearchOperationHandle operation(SearchRequest request)
Description copied from interface:ConnectionCreates a handle for a search operation.- Parameters:
request- search request- Returns:
- search operation handle
-
write
protected void write(DefaultOperationHandle<?,?> handle)
Description copied from class:TransportConnectionWrite the request in the supplied handle to the LDAP server. This method does not throw, it should report exceptions to the handle.- Specified by:
writein classTransportConnection- Parameters:
handle- for the operation write
-
complete
protected void complete(DefaultOperationHandle<?,?> handle)
Description copied from class:TransportConnectionReport that the supplied handle has completed. Allows the connection to clean up any resources associated with the handle.- Specified by:
completein classTransportConnection- Parameters:
handle- that has completed
-
getAndIncrementMessageID
int getAndIncrementMessageID()
Returns the value of the next message ID and increments the counter.- Returns:
- message ID
-
getMessageID
int getMessageID()
Returns the value of the next message ID.- Returns:
- message ID
-
setMessageID
void setMessageID(int i)
Sets the value of the next message ID.- Parameters:
i- message ID
-
getChannelOptions
Map<io.netty.channel.ChannelOption,Object> getChannelOptions()
Returns the channel options.- Returns:
- channel options
-
getIoWorkerGroup
io.netty.channel.EventLoopGroup getIoWorkerGroup()
Returns the I/O worker group.- Returns:
- I/O worker group
-
getMessageWorkerGroup
io.netty.channel.EventLoopGroup getMessageWorkerGroup()
Returns the message worker group.- Returns:
- message worker group
-
close
public void close(RequestControl... controls)
Closes this connection. Abandons all pending responses and sends an unbind to the LDAP server if the connection is open when this method is invoked.- Parameters:
controls- to send with the unbind request when closing the connection
-
notifyOperationHandlesOfClose
private void notifyOperationHandlesOfClose()
Sends an exception notification to all pending responses that the connection has been closed. Since this invokes any configured exception handlers, notifications will use themessageWorkerGroupif it is configured.
-
reconnect
private void reconnect()
Attempts to reestablish the channel for this connection.- Throws:
IllegalStateException- if the connection is open
-
isOpen
public boolean isOpen()
Returns whether the underlying Netty channel is open. SeeChannel.isOpen().- Returns:
- whether the Netty channel is open
-
isOpening
private boolean isOpening()
Returns whether this connection is currently attempting to open.- Returns:
- whether the Netty channel is in the process of opening
-
isClosing
private boolean isClosing()
Returns whether this connection is currently attempting to close.- Returns:
- whether the Netty channel is in the process of closing
-
throwIfClosed
private void throwIfClosed() throws LdapExceptionThrows an exception if the Netty channel is closed. SeeisOpen().- Throws:
LdapException- if the connection is closed
-
-