Development Guide

Example - First Proxy

Everything is ready now to create our first proxy.

Proxy

First thing we need is to create our proxy that will contain all the application logic (spawning connections, closing connections).

proxy.ExampleProxy
/**
 * Example proxy, which starts configured number of example connections.
 */
public class ExampleProxy extends Proxy {
    private ExampleProxyConfig config;

    private ExampleConnectionManager connectionManager;

    public ExampleProxy(ProxyModule module, PetepHelper helper, ExampleProxyConfig config) {
        super(module, helper);
        this.config = config;
    }

    @Override
    public ConnectionManager getConnectionManager() {
        return connectionManager;
    }

    @Override
    public boolean prepare() {
        Logger.getGlobal().info("Example proxy prepared!");

        connectionManager = new ExampleConnectionManager(helper);

        return true;
    }

    @Override
    public boolean start() {
        Logger.getGlobal().info("Example proxy started!");

        for (var i = 0; i < config.getConnectionCount(); ++i) {
            var code = connectionManager.generateCode();
            var connection = new ExampleConnection(code, this, "ec_" + code);

            if (connection.start()) {
                connectionManager.add(connection);
            }
        }

        return true;
    }

    @Override
    public void stop() {
        connectionManager.stop();

        Logger.getGlobal().info("Example proxy stopped!");
    }

    @Override
    public boolean supports(PDU pdu) {
        return pdu instanceof ExamplePdu;
    }
}

Proxy Module

Well done, our proxy logic is prepared. Now we need to create module that will allow user to add our proxy to the list of proxies in PETEP.

proxy.ExampleProxyModule
/**
 * Example proxy module for creating example proxy.
 */
public class ExampleProxyModule extends ProxyModule implements Configurable<ExampleProxyConfig> {
    private ExampleProxyConfig config;

    public ExampleProxyModule(
            ProxyModuleFactory factory,
            String code,
            String name,
            String description,
            boolean enabled) {
        super(factory, code, name, description, enabled);
    }

    @Override
    public Proxy createProxy(PetepHelper helper) {
        return new ExampleProxy(this, helper, config);
    }

    @Override
    public void loadConfig(ExampleProxyConfig config) {
        Logger.getGlobal().info("Example proxy configuration loaded!");

        this.config = config;
    }

    @Override
    public ExampleProxyConfig saveConfig() {
        Logger.getGlobal().info("Example proxy configuration saved!");

        return config;
    }
}

Notice that our module implements Configurable interface that allows it to store the proxy configuration in the project.

Proxy Module Factory

Now we can create a factory that will create the modules.

proxy.ExampleProxyModuleFactory
/**
 * Example proxy module factory for creating example proxy modules.
 */
public class ExampleProxyModuleFactory extends ProxyModuleFactory
        implements Configurator<ExampleProxyConfig>, ProxySerializer, ProxyDeserializer {
    public ExampleProxyModuleFactory(Extension extension) {
        super(extension);
    }

    @Override
    public String getCode() {
        return "example-proxy";
    }

    @Override
    public String getName() {
        return "Example Proxy";
    }

    @Override
    public ProxyModule createModule(String code, String name, String description, boolean enabled) {
        return new ExampleProxyModule(this, code, name, description, enabled);
    }

    @Override
    public ConfigPane<ExampleProxyConfig> createConfigPane() throws IOException {
        return new ExampleProxyConfigurator();
    }

    @Override
    public Optional<PduMetadataPane> createPduMetadataPane() throws IOException {
        return Optional.of(new ExamplePduMetadataPane());
    }

    @Override
    public ProxySerializer getSerializer() {
        return this;
    }

    @Override
    public ProxyDeserializer getDeserializer() {
        return this;
    }

    @Override
    public Map<String, String> serializePduMetadata(PDU pdu) {
        ExamplePdu temp = (ExamplePdu) pdu;
        return Map.of(
                "StringParam",
                temp.getStringParam(),
                "IntegerParam",
                String.valueOf(temp.getIntegerParam()));
    }

    @Override
    public Optional<PDU> deserializePdu(Proxy proxy,
                              Connection connection,
                              PduDestination destination,
                              byte[] buffer,
                              int size,
                              Charset charset,
                              Set<String> tags,
                              Map<String, String> metadata) {
        return Optional.of(new ExamplePdu(
                proxy,
                connection,
                destination,
                buffer,
                size,
                charset,
                tags,
                metadata.get("StringParam"),
                Integer.parseInt(metadata.get("IntegerParam"))));
    }
}

Notice the following things:

  • We create our metadata pane from previous chapter in createPduMetadataPane() method, so that users can use it in GUI (for example in internal Catcher extension).
  • Our factory implements Configurator interface and returns our configuration pane, so that users can configure the proxy in Settings GUI.
  • For simplicity, our factory implements proxy Serializer and Deserializer, so that we can easily provide the serialization logic and serialize our metadata to HashMap of strings.

We are almost done, we just have to register our factory to the PETEP in out PetepExtension.init() method.

petep.Extension: public void init(ExtensionHelper helper)
helper.registerProxyModuleFactory(new ExampleProxyModuleFactory(this));

Awesome! Now we can deploy our extension and enjoy our new proxy!