Class AsyncSecureDatagramSocket
- java.lang.Object
-
- net.sf.eBus.net.AsyncChannel
-
- net.sf.eBus.net.AbstractAsyncDatagramSocket
-
- net.sf.eBus.net.AsyncDatagramSocket
-
- net.sf.eBus.net.AsyncSecureDatagramSocket
-
public final class AsyncSecureDatagramSocket extends AsyncDatagramSocket
This class extendsAsyncDatagramSocket
(which see) by providing an ability to create a secure connection using DTLS. The steps to create and open a secure datagram socket are the same asAsyncDatagramSocket
with the following differences-
A
AsyncSecureDatagramSocket.SecureDgramSocketBuilder
is used to create a secure datagram socket and a builder instance is obtained by callingAsyncDatagramSocket.builder()
. -
A
SecureDatagramListener
must be provided and not aDatagramListener
. -
Connecting
to a peer requires aDTLS context
. Note: insecureconnecting
is not supported and will result in anUnsupportedOperationException
.
A secure datagram socket is opened using
AsyncDatagramSocket.open
methods. Once opened insecure data may be transmitted to a specifiedaddress
either as raw bytes or using aDatagramBufferWriter
. Once connected targeted sends are not allowed - which is no change fromAsyncDatagramSocket
. Targeted sends may be done again once the secure datagram socket isdisconnected
.In terms of the
DatagramBufferWriter
, thefill
method must return an address when disconnected andnull
when connected.The biggest difference is in the connection process. There is a time lag between requesting a secure connection and connection completion. When the secure connection is successfully completed the listener is informed via the
SecureDatagramListener.handleConnect(AsyncSecureDatagramSocket)
callback. If secure connection failed, thenSecureDatagramListener.handleDisconnect(Throwable, AsyncSecureDatagramSocket)
is called. While the secure connection is being set up no application data may be transmitted - either targeted or not.Building, Opening a Secure Async UDP Socket
The following example code shows how to create, open, and securely connect anAsyncSecureDatagramSocket
. VariabledgramListener
contains aSecureDatagramListener
instance anddtlsContext
a DTLS-typeSSLContext
instance.final SocketAddress bindAddress = new InetSocketAddress(bindPort); final SocketAddress peerAddress = new InetSocketAddress(peerAddress, peerPort); final AsyncSecureDatagramSocket.SecureDgramSocketBuilder builder = AsyncSecureDatagramSocket.secureBuilder(); final AsyncSecureDatagramSocket socket = builder.inputBufferSize(512) // Optional. Defaults to ENetConfigure.DEFAULT_BUFFER_SIZE. .outputBufferSize(512) // Optional. Defaults to ENetConfigure.DEFAULT_BUFFER_SIZE. .byteOrder(ByteOrder.BIG_ENDIAN) // Optional. Defaults to ByteOrder.LITTLE_ENDIAN .listener(dgramListener) // Required. Must be a SecureDatagramListener instance. .selector("dgramSelector") // Optional. Defaults to AsyncChannel.defaultSelector(). .buiild(); socket.open(bindAddress); // Set to true when connect process completes, successfully or not. mConnectComplete = false; // Set to true when connect process successfully completes. mIsConnected = false; // Start the secure datagram connection process as the initiating client. socket.connect(peerAddress, true, dtlsContext); // Wait for the connection to complete. mConnectLock.lock(); try { while (!mConnectComplete) { mConnected.await(); } } finally { mConnectLock.unlock(); } // Did the secure datagram connection complete successfully? if (mIsConnected) { // Yes. Start sending application data. } else { // No. Handle this situation. }
Secure Datagram Listener
TheSecureDatagramListener handleConnect
andhandleDisconnect
methods are defined as follows:@Override public void handleConnect(final AsyncSecureDatagramSocket socket) { // Secure connection successfully completed. mIConnected = true; mConnectLock.lock(); try { mConnectComplete = true; mConnected.signal(); } finally { mConnectLock.unlock(); } } @Override public void handleDisconnect(final Throwable t, final AsyncSecureDatagramSocket socket) { // Secure connection unsuccessfully completed. mIConnected = false; mConnectLock.lock(); try { mConnectComplete = true; mConnected.signal(); } finally { mConnectLock.unlock(); } }
Disconnecting and Closing a Secure Async UDP Socket
Since UDP is a connection-less protocol, there is no concept of closing a DTLS connection. Once a DTLS session is established between two datagram sockets there is no way to terminate this session at this API level. Calling
disconnect()
drops the UDP "connection" and drops the DTLS engine - but the peer is not informed of this fact. If this datagram socket then sends insecure data to the peer, the peer will treat it as secure and attempt tounwrap
the data which will fails with anSSLException
.Having both ends of a UDP "connection" stop secure data transmission is an application-layer issue. One side would initiate the "disconnect" resulting in both sides calling
disconnect()
and dropping their DTLS engines. The same issue applies toclosing
a datagram socket.Note: eBus does not contain any security, cipher, or encryption code itself. eBus uses the security features provided by the Java platform to implement a secure UDP connection.
-
A
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
AsyncSecureDatagramSocket.SecureDgramSocketBuilder
Constructs anAsyncSecureDatagramSocket
instance based on the parameters set via this builder API.-
Nested classes/interfaces inherited from class net.sf.eBus.net.AsyncDatagramSocket
AsyncDatagramSocket.DatagramBuilder
-
Nested classes/interfaces inherited from class net.sf.eBus.net.AbstractAsyncDatagramSocket
AbstractAsyncDatagramSocket.AbstractDatagramBuilder<B extends AbstractAsyncDatagramSocket.AbstractDatagramBuilder<?>>
-
Nested classes/interfaces inherited from class net.sf.eBus.net.AsyncChannel
AsyncChannel.BufferMode, AsyncChannel.ChannelBuilder<B extends AsyncChannel.ChannelBuilder<?>>, AsyncChannel.ConnectState
-
-
Field Summary
-
Fields inherited from class net.sf.eBus.net.AbstractAsyncDatagramSocket
mBoundFlag, mListener, mOpenFlag, sLogger
-
Fields inherited from class net.sf.eBus.net.AsyncChannel
LOCALHOST, mChannel, mInputBuffer, mLocalAddress, mOutputBuffer, mOutputLock, mRemoteAddress, mSelectorThread
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
connect(java.net.SocketAddress remoteAddr)
ThrowsUnsupportedOperationException
because insecure datagram connections are not supported byAsyncSecureDatagramSocket
.void
connect(java.net.SocketAddress remoteAddr, boolean isClient, javax.net.ssl.SSLContext sslContext)
"Connects" this datagram to the remote address usingAsyncDatagramSocket.connect(SocketAddress)
to perform parameter validation and the actual connection.void
disconnect()
Disconnects the UDP "connection" to the peer and drops the DTLS engine used for secure communication.protected void
doClose()
Marks the channel as closed.protected void
doOpen(java.net.SocketAddress bindAddr, java.net.ProtocolFamily family)
After successfully opening a datagram channel, marks this datagram socket as ready for secure connection.protected void
doOpen(java.nio.channels.DatagramChannel channel)
Encapsulates the given datagram channel and then marks this secure datagram socket as disconnected.protected boolean
doRead()
Returnstrue
if a packet was successfully received (meaning there could be more packets to follow) andfalse
if no packet was received (meaning there are no more packets available at this time).protected void
doSend(byte[] b, int off, int len, java.net.SocketAddress peer)
Places given bytes into outbound buffer, encrypts those bytes, and then sends those encrypted bytes to the targeted far-end address.protected void
doSend(DatagramBufferWriter writer)
Useswriter
to directly write data to outbound TLS buffer.boolean
isReadyToSend()
Returnstrue
if DTLS handshake is successfully completed and application data may now be transmitted on this secure datagram socket.static AsyncSecureDatagramSocket.SecureDgramSocketBuilder
secureBuilder()
Returns a new secure datagram builder instance used to create anAsyncSecureDatagramSocket
instance.-
Methods inherited from class net.sf.eBus.net.AsyncDatagramSocket
builder, isConnected, open, open, open, open, open, send, send, send, send, send, send, send
-
Methods inherited from class net.sf.eBus.net.AbstractAsyncDatagramSocket
close, closeNow, datagramSocket, isBound, isOpen, opened, write
-
Methods inherited from class net.sf.eBus.net.AsyncChannel
createSelector, defaultSelectorName, getOption, inputBufferSize, isSelector, localSocketAddress, outputBufferSize, remoteSocketAddress, selectorNames, setOption, supportedOptions
-
-
-
-
Method Detail
-
connect
public void connect(java.net.SocketAddress remoteAddr) throws java.io.IOException
ThrowsUnsupportedOperationException
because insecure datagram connections are not supported byAsyncSecureDatagramSocket
. Seeconnect(SocketAddress, boolean, SSLContext)
for instructions on making a secure datagram connection.- Overrides:
connect
in classAsyncDatagramSocket
- Parameters:
remoteAddr
- connect to this remote address.- Throws:
java.lang.UnsupportedOperationException
- because insecure datagram connections are not supported.java.io.IOException
- not thrown by this method but required for override.- See Also:
connect(SocketAddress, boolean, SSLContext)
,disconnect()
-
disconnect
public void disconnect() throws java.io.IOException
Disconnects the UDP "connection" to the peer and drops the DTLS engine used for secure communication. This means this datagram socket may be used again for targeted insecure communications.Note: DTLS does not have a closing handshake protocol. That is because UDP is a connection-less communication protocol and so there is nothing to disconnect. Terminating a DTLS connection on both sides is an application-level issue. One side must inform the other that secure communications are being terminated so both sides know to stop using their DTLS engine. If one side unilaterally stops using secure data transmission, the other side will still attempt to unwrap the input which will fail.
This method may be invoked at any time. It will not have any effect on read or write operations already in progress when invoked.
Does nothing if this datagram socket is closed or disconnected.
- Overrides:
disconnect
in classAsyncDatagramSocket
- Throws:
java.io.IOException
- if some I/O error occurs.- See Also:
connect(SocketAddress, boolean, SSLContext)
,AbstractAsyncDatagramSocket.close()
,AbstractAsyncDatagramSocket.closeNow()
-
doClose
protected void doClose()
Marks the channel as closed. IfnowFlag
istrue
and socket is open, then performs a secure DTLS closing handshake before closing the datagram socket.- Overrides:
doClose
in classAbstractAsyncDatagramSocket
- See Also:
AbstractAsyncDatagramSocket.doClose()
-
doOpen
protected void doOpen(java.net.SocketAddress bindAddr, java.net.ProtocolFamily family) throws java.io.IOException
After successfully opening a datagram channel, marks this datagram socket as ready for secure connection.- Overrides:
doOpen
in classAsyncDatagramSocket
- Parameters:
bindAddr
- bind the local address to this port.family
- communication protocol family.- Throws:
java.io.IOException
- if attempt to open datagram channel fails.- See Also:
AsyncDatagramSocket.doOpen(SocketAddress, ProtocolFamily)
,doClose()
-
doOpen
protected void doOpen(java.nio.channels.DatagramChannel channel) throws java.io.IOException
Encapsulates the given datagram channel and then marks this secure datagram socket as disconnected.- Overrides:
doOpen
in classAsyncDatagramSocket
- Parameters:
channel
- use this datagram channel.- Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
AsyncDatagramSocket.doOpen(DatagramChannel)
,doClose()
-
doRead
protected boolean doRead() throws java.io.IOException
Returnstrue
if a packet was successfully received (meaning there could be more packets to follow) andfalse
if no packet was received (meaning there are no more packets available at this time).- Overrides:
doRead
in classAbstractAsyncDatagramSocket
- Returns:
true
if a packet was successfully received.- Throws:
java.io.IOException
- if attempt to receive datagram packet failed due to I/O problems.
-
doSend
protected void doSend(byte[] b, int off, int len, java.net.SocketAddress peer) throws java.io.IOException
Places given bytes into outbound buffer, encrypts those bytes, and then sends those encrypted bytes to the targeted far-end address.- Overrides:
doSend
in classAbstractAsyncDatagramSocket
- Parameters:
b
- endlen
bytes from this array starting atoff
offset.off
- offset intob
.len
- send this many bytes fromb
.peer
- set tonull
and ignored since configured far-end address is used.- Throws:
java.nio.channels.NotYetConnectedException
- ifpeer
isnull
and the opening handshake with the peer is not successfully completed.java.io.IOException
- if the data encryption or transmission fails.
-
doSend
protected void doSend(DatagramBufferWriter writer) throws java.io.IOException
Useswriter
to directly write data to outbound TLS buffer. This by-passes the need to write data to a byte array first and then place that array into the outbound TLS buffer. If this datagram socket is not connected to a peer, then usesAsyncDatagramSocket.doSend(DatagramBufferWriter)
to transmit the data; otherwise wraps the contents before transmitting.- Overrides:
doSend
in classAsyncDatagramSocket
- Parameters:
writer
- writes the next available packet to the outbound TLS byte buffer.- Throws:
java.io.IOException
- if the data encryption or transmission fails.
-
isReadyToSend
public boolean isReadyToSend()
Returnstrue
if DTLS handshake is successfully completed and application data may now be transmitted on this secure datagram socket. Otherwise returnsfalse
.- Returns:
true
if ready to send application data.
-
connect
public void connect(java.net.SocketAddress remoteAddr, boolean isClient, javax.net.ssl.SSLContext sslContext) throws java.io.IOException
"Connects" this datagram to the remote address usingAsyncDatagramSocket.connect(SocketAddress)
to perform parameter validation and the actual connection. Once successfully connected, then creates the DTLS engine and begins the opening security handshake process.Note: application data may not be transmitted until the opening handshake is successfully completed. The user is informed of this completion via
SecureDatagramListener.handleConnect(AsyncSecureDatagramSocket)
callback. If the opening handshake fails, then this datagram socket is closed.- Parameters:
remoteAddr
- connect to this remote address.isClient
-true
if this is the DTLS client-side andfalse
if server-side.sslContext
- context used to create DTLS engine.- Throws:
java.lang.NullPointerException
- ifremoteAddr
orsslContext
isnull
.java.lang.IllegalArgumentException
- ifsslContext
is not DTLS.java.lang.IllegalStateException
- if datagram socket is already connected or closed.java.io.IOException
- if some I/O error occurs.- See Also:
AsyncDatagramSocket.connect(SocketAddress)
,disconnect()
-
secureBuilder
public static AsyncSecureDatagramSocket.SecureDgramSocketBuilder secureBuilder()
Returns a new secure datagram builder instance used to create anAsyncSecureDatagramSocket
instance.- Returns:
- new
AsyncSecureDatagramSocket
builder instance.
-
-