Deep Dive into smart‑socket’s Built‑In Plugin System

This article explains smart‑socket’s extensible plugin architecture, detailing the Plugin and AbstractPlugin interfaces, and demonstrates how to integrate built‑in plugins such as SSL/TLS encryption, heartbeat detection, blacklist filtering, memory‑pool monitoring, traffic logging, socket option configuration, and idle‑state handling, while covering plugin ordering, custom development, performance considerations, and best‑practice recommendations.

Three Knives
Three Knives
Three Knives
Deep Dive into smart‑socket’s Built‑In Plugin System

Plugin Architecture

smart‑socket plugin system is based on the Plugin interface, which extends NetMonitor . It defines three extension points:

preProcess : preprocesses a request message and decides whether the message should continue to MessageProcessor.process. Returning false drops the message.

stateEvent : listens to state‑machine events for a session.

NetMonitor methods: monitor connection acceptance, read/write operations, etc.

public interface Plugin<T> extends NetMonitor {
    boolean preProcess(AioSession session, T t);
    void stateEvent(StateMachineEnum stateMachineEnum, AioSession session, Throwable throwable);
}

To simplify development, AbstractPlugin provides empty implementations of all Plugin methods.

public abstract class AbstractPlugin<T> implements Plugin<T> {
    @Override public boolean preProcess(AioSession session, T t) { return true; }
    @Override public void stateEvent(StateMachineEnum stateMachineEnum, AioSession session, Throwable throwable) {}
    // other NetMonitor methods have empty bodies
}

Plugins are added to a MessageProcessor via addPlugin and the processor is passed to an AioQuickServer instance.

MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
    @Override public void process0(AioSession session, String msg) {
        // handle message
    }
};
processor.addPlugin(new SslPlugin<>());
processor.addPlugin(new HeartPlugin<>());
AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
server.start();

SSL/TLS Security Plugin

SslPlugin provides SSL/TLS encryption by wrapping the underlying AsynchronousSocketChannel.

public class SslServerExample {
    public static void main(String[] args) throws Exception {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received encrypted message: " + msg);
            }
        };
        ServerSSLContextFactory factory = new ServerSSLContextFactory();
        factory.keystore("keystore.jks", "password");
        SslPlugin<String> sslPlugin = new SslPlugin<>(factory);
        processor.addPlugin(sslPlugin);
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Heartbeat Detection Plugin

HeartPlugin detects active connections and prevents dead connections caused by network anomalies.

public class CustomHeartPlugin extends HeartPlugin<String> {
    public CustomHeartPlugin() {
        super(30, 60, TimeUnit.SECONDS); // interval 30 s, timeout 60 s
    }
    @Override public void sendHeartRequest(AioSession session) throws IOException {
        byte[] heartMsg = "PING".getBytes();
        session.writeBuffer().writeInt(heartMsg.length);
        session.writeBuffer().write(heartMsg);
    }
    @Override public boolean isHeartMessage(AioSession session, String msg) {
        return "PING".equals(msg) || "PONG".equals(msg);
    }
}
public class HeartPluginExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                if ("PING".equals(msg)) {
                    byte[] resp = "PONG".getBytes();
                    session.writeBuffer().writeInt(resp.length);
                    session.writeBuffer().write(resp);
                    session.writeBuffer().flush();
                } else {
                    System.out.println("Received message: " + msg);
                }
            }
        };
        processor.addPlugin(new CustomHeartPlugin());
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Blacklist Plugin

BlackListPlugin rejects connections from specific IP addresses or port ranges.

public class BlackListExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received message: " + msg);
            }
        };
        BlackListPlugin<String> blackListPlugin = new BlackListPlugin<>();
        // Reject a specific IP
        blackListPlugin.addRule(address -> !"192.168.1.100".equals(address.getAddress().getHostAddress()));
        // Reject ports outside 10000‑20000
        blackListPlugin.addRule(address -> {
            int port = address.getPort();
            return port < 10000 || port > 20000;
        });
        processor.addPlugin(blackListPlugin);
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Memory‑Pool Monitoring Plugin

BufferPageMonitorPlugin monitors the usage of the memory pool.

public class BufferPageMonitorExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received message: " + msg);
            }
        };
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        // Output memory‑pool status every 6 seconds
        processor.addPlugin(new BufferPageMonitorPlugin<>(server, 6));
        server.start();
    }
}

Traffic Monitoring Plugin

StreamMonitorPlugin logs the data flow of the network layer, showing hex dumps in real time.

public class StreamMonitorExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received message: " + msg);
            }
        };
        processor.addPlugin(new StreamMonitorPlugin<>());
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Sample console output:

2023-01-01 10:00:00.123 [ /127.0.0.1:56789 --> /127.0.0.1:8888 ] [ read: 12 bytes ]
00000000h: 48 65 6c 6c 6f 20 57 6f 72 6c 64 21   ; Hello World!

Socket Option Plugin

SocketOptionPlugin configures various socket options.

public class SocketOptionExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received message: " + msg);
            }
        };
        SocketOptionPlugin<String> socketOptionPlugin = new SocketOptionPlugin<>();
        socketOptionPlugin.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
        socketOptionPlugin.setOption(StandardSocketOptions.SO_RCVBUF, 1024 * 1024);
        socketOptionPlugin.setOption(StandardSocketOptions.SO_SNDBUF, 1024 * 1024);
        processor.addPlugin(socketOptionPlugin);
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Idle‑State Plugin

IdleStatePlugin detects idle connections and automatically closes them after a configured period without read/write activity.

public class IdleStateExample {
    public static void main(String[] args) throws IOException {
        MessageProcessor<String> processor = new AbstractMessageProcessor<>() {
            @Override public void process0(AioSession session, String msg) {
                System.out.println("Received message: " + msg);
            }
        };
        // Close connection if idle for 60 seconds
        processor.addPlugin(new IdleStatePlugin<>(60));
        AioQuickServer<String> server = new AioQuickServer<>(8888, new StringProtocol(), processor);
        server.start();
    }
}

Plugin Execution Order

Plugins execute in the order they are added. If any plugin’s preProcess returns false, subsequent plugins are skipped and the message is not passed to the MessageProcessor.

// Example order
processor.addPlugin(plugin1); // executed first
processor.addPlugin(plugin2); // executed second
processor.addPlugin(plugin3); // executed last

Best‑Practice Recommendations

Use plugins wisely: select only needed plugins to avoid unnecessary performance overhead.

Mind plugin order: execution order can affect functionality; arrange accordingly.

Custom plugin development: inherit AbstractPlugin for special requirements.

Monitor plugin performance: monitoring plugins may introduce overhead; balance monitoring needs with performance.

Exception handling: handle exceptions inside plugins to prevent disruption of the main processing flow.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamonitoringSSLheartbeatplugin systemblacklistsmart-socket
Three Knives
Written by

Three Knives

Every line of code you contribute to open source could help make the future better.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.