Java Multi-Threaded Non-Blocking IO(NIO) Secure Protocol Framework
Introducing XlogistX.IO Java Multi-Threaded Secure NIO framework for quick and easy networking protocol implementation and deployments.
The pillars of the framework are:
The framework is an alternative to Netty or Mina with minimal dependencies and small code footprint. It can be easily deployed on a Raspberry PI Zero(for small IoT projects) or on high-end rack mountable servers without sacrificing performance, security and portability.
The framework takes care of all the complexity of networking accepting/closing connections, detecting incoming data, reading raw bytes from ServerSocketChannel, managing the thread allocation and finally invoking the SessionCallback where the protocol implementation takes place.
The SessionCallback is the heart of the implementation.t receives raw data via a ByteBuffer, it assembles the request, processes the request and creates/sends back a response to the caller. Two abstract implementations of the SessionCallback could be extended, the PlainSessionCallback and the SSLSessionCallback(Secure TLS). The user simply implements the accept(ByteBuffer bb) method, the EchoProtocol Java code illustrates a complete and functional code of a simple echo protocol.
The SessionCallback is already implemented for following protocols:
The tcp tunneling is mainly used to expose services through a firewall
An experimental web server that supports
An echo chat protocol
NIO Protocols currently implemented and deployed
System | OS | Core | HyperThread | RAM | |
Dell laptop | Linux Ubuntu 22.04 | 4 | 8 | 32GB | |
Tested Service | TimeStamp | Total duration | Count | Rate /second | Average/millis |
HTTPS | Feb 17, 2023 12:57:39 PM | 0:01:36 | 100000 | 1038.0767 | 59.8584 |
HTTP | Feb 17, 2023 6:50:36 PM | 0:00:22 | 500000 | 22558 | 3.11532 |
NIO stands for Non-blocking Input Output, it is the opposite of the standard stream architecture that requires a dedicated thread waiting for reading incoming data via the input stream. NIO uses signaling mechanism within the OS to detect packet activities such as:
To detect the different IO activities,a thread will be dedicated to poll on registered selection keys using a selector object. The selector object wakes up from the select mode once IO activities are detected. Based on the IO activities type a new connection is established, incoming data are available for reading or a connection closure is detected.
To simplify and create an extensible multithreaded design 5 classes are used to implement the NIO framework:
The NIOSocket is the main entry point class or object of the framework it uses Executor to multithread activities of IO operations, it is responsible for:
The ProtocolFactory is responsible for:
The ProtocolHandler is responsible for:
The SessionCallback is the callback instance invoked after reading raw data via the ProtocolHandler. The SessionCallback is responsible for:
The ChannelOutputStream is an output stream based on a ChannelSocket which behaves similar to an OutputStream for all practical purposes.
TLS stands for Transport Layer Security. It uses cryptographic keys to communicate securely between 2 parties (e.g. client and server).
Two types of keys are used to establish secure communication, a public/private asymmetric keypair and a symmetric temporary/session key.
After establishing a connection between client and server, a key exchange process takes place to negottate the following:
In a nutshell, this is a very simplified overview of how TLS works. The truth is it is way more complicated.
Initially I was too lazy to do the hard work so I decided to google any existing reference implementation and surprise, surprise nothing really worked, the Java documentation was useless, any github implementation covered specific protocol version or specific ciphers, no luck on stackoverflow either.
I guess the main reason is the Java SSLEngine handshaking complexity and behavior. I even asked chatGBT recently to give a Java TLS example, guess what useless again!!!, it seems that it grabbed the code from stackoverflow or something similar.
The SSLEngine is the core object that manages the handshaking and data encryption/decryption in Java, it behaves as a state machine that generates handshake status and result status after every SSL operation.
Luckily, at the start of COVID, I designed a simple and extensible State Machine package and then later on, I decided to implement SSLNIOSocket as a state machine. It was a perfect solution for a very complex problem: no need to figure out how to start the handshake, what transition is next, when the handshake is done, no need to check protocol version or cipher type.
As mentioned earlier, the SSL Engine is a state machine so in order to implement SSLNIOSocket a state machine is implemented to process SSLEngine handshake stages. The state machine algorithm behaves as follow:
SSLEngine Status | State | Description |
BeginHandshake | Init state | Triggering the handshake process and setting the configuration parameters of the sslengine like data buffers, supported protocol and ciphers |
NEED_WRAP | Handshaking | Wrapping data to be sent back to the caller during handshake process like protocol and cipher agreement, or key exchange agreement |
NEED_UNWRAP | Handshaking | Reading data from the caller during handshake |
NEED_TASK | Handshaking | mainly used for key generating and singing |
FINISHED | Handshaking | Last step of the handshaking state |
NOT_HANDSHAKING | DataReady | No more handshake ready to exchange application encrypted and decrypted data |