All Downloads are FREE. Search and download functionalities are using the official Maven repository.

automately.core.services.sdk.SdkSockJSServer Maven / Gradle / Ivy

package automately.core.services.sdk;

import automately.core.services.core.AutomatelyService;
import com.hazelcast.core.IMap;
import io.jcluster.core.Cluster;
import io.jcluster.core.Config;
import io.jcluster.core.Logger;
import io.jsync.Async;
import io.jsync.AsyncResult;
import io.jsync.Handler;
import io.jsync.eventbus.EventBus;
import io.jsync.eventbus.Message;
import io.jsync.json.JsonArray;
import io.jsync.json.JsonObject;
import io.jsync.sockjs.EventBusBridgeHook;
import io.jsync.sockjs.SockJSServer;
import io.jsync.sockjs.SockJSSocket;

import java.util.*;

/**
 * The SdkSockJSServer is the default SockJS server for handling any SDK Operations
 */
public class SdkSockJSServer extends AutomatelyService {

    // TODO Complete JavaDocs
    // We want to set the sessions

    private io.jsync.http.HttpServer httpServer;

    private Logger logger;

    @Override
    public void start(Cluster owner) {

        Async async = owner.async();

        Config config = owner.config();

        if (!coreConfig().containsField("sdk_httpserver_host")) coreConfig().putValue("sdk_httpserver_host", "0.0.0.0");
        if (!coreConfig().containsField("sdk_httpserver_port")) coreConfig().putValue("sdk_httpserver_port", 9080);

        config.save();

        this.logger = owner.logger();

        httpServer = async.createHttpServer();

        JsonObject bridgeConfig = new JsonObject();
        bridgeConfig.putString("auth_address", "automately.sdk.auth.authorise");

        // Increased auth_timeout
        bridgeConfig.putNumber("auth_timeout", 24 * 60 * 1000);
        // We are increasing the amount to 25.
        bridgeConfig.putNumber("max_handlers_per_socket", 25);

        // Handlers we can send messages to from the client side..
        JsonArray confInbound = new JsonArray();
        // Handlers we can bind to from the client side..
        JsonArray confOutbound = new JsonArray();

        JsonObject sdkAuth = new JsonObject();
        sdkAuth.putString("address_re", "automately.sdk.auth..+");
        confInbound.add(sdkAuth);

        // Used to retrieve info about jobs and such
        JsonObject sdkJob = new JsonObject();
        sdkJob.putString("address_re", "automately.sdk.job..+");
        sdkJob.putBoolean("requires_auth", true);
        confInbound.add(sdkJob);

        // Allow messageBus messages to be sent to public handlers
        JsonObject sdkMessageBusOutbound = new JsonObject();
        sdkMessageBusOutbound.putString("address", "automately.sdk.messageBus");
        sdkMessageBusOutbound.putBoolean("requires_auth", true);
        confInbound.add(sdkMessageBusOutbound);

        JsonObject sdkMessageBusInbound = new JsonObject();
        sdkMessageBusInbound.putString("address_re", "automately.sdk.messageBus..+");
        sdkMessageBusInbound.putBoolean("requires_auth", true);
        confOutbound.add(sdkMessageBusInbound);

        SockJSServer sockJSServer = owner.async().createSockJSServer(httpServer);

        // We utilize a hook so we can intercept all handlers that need to be mapped to the client
        sockJSServer.setHook(new EventBusBridgeHook() {

            private IMap clientMessageBusHandlers = cluster().data().getMap("sdk.messageBus.handlers");

            private HashMap>>>> registeredHandlers = new HashMap<>();

            private EventBus eventBus = cluster().eventBus();

            public boolean handleSocketCreated(SockJSSocket sock) {
                return true;
            }

            @Override
            public void handleSocketClosed(SockJSSocket sock) {
                List>>> handlers = registeredHandlers.get(sock);
                if (handlers != null) {
                    for (Map.Entry>> entry : handlers) {
                        Map.Entry> entry1 = entry.getValue();
                        eventBus.unregisterHandler(entry1.getKey(), entry1.getValue());
                    }
                }
                registeredHandlers.remove(sock);
            }

            @Override
            public boolean handleSendOrPub(SockJSSocket sock, boolean send, JsonObject msg, String address) {
                return true;
            }

            @Override
            public boolean handlePreRegister(SockJSSocket sock, String address) {

                if (address.startsWith("automately.sdk.messageBus.")) {
                    if (!clientMessageBusHandlers.containsKey(address)) {
                        return false;
                    }
                    String internalIdentifier = clientMessageBusHandlers.get(address);

                    Handler handler = event -> eventBus.send(address, event.body());

                    eventBus.registerHandler(internalIdentifier, handler);

                    List>>> list = registeredHandlers.get(sock);

                    if (list == null) {
                        registeredHandlers.put(sock, list = new ArrayList<>());
                    }

                    list.add(new AbstractMap.SimpleEntry<>(address, new AbstractMap.SimpleEntry<>(internalIdentifier, handler)));

                    clientMessageBusHandlers.remove(address);

                    return true;
                }
                return true;
            }

            @Override
            public void handlePostRegister(SockJSSocket sock, String address) {

            }

            @Override
            public boolean handleUnregister(SockJSSocket sock, String address) {
                List>>> handlers = registeredHandlers.get(sock);
                if (handlers != null) {
                    for (Map.Entry>> entry : handlers) {
                        if (entry.getKey().equals(address)) {
                            Map.Entry> routeHandler = entry.getValue();
                            eventBus.unregisterHandler(routeHandler.getKey(), routeHandler.getValue());
                        }
                    }
                }
                return true;
            }

            @Override
            public boolean handleAuthorise(JsonObject message, String sessionID, Handler> handler) {
                return false;
            }
        });

        sockJSServer.bridge(new JsonObject().putString("prefix", "/automately.sdk.eventBus"), confInbound, confOutbound, bridgeConfig);

        // Optimization.
        httpServer.setMaxWebSocketFrameSize(262144);

        // Done with our exposing..
        httpServer.listen(coreConfig().getValue("sdk_httpserver_port"), coreConfig().getValue("sdk_httpserver_host"), asyncResult -> {
            if (!asyncResult.succeeded()) {
                logger.fatal("Could not start DefaultHttpServer on " + coreConfig().getValue("sdk_httpserver_host") + ":" + coreConfig().getValue("sdk_httpserver_port"));
                return;
            }
            logger.info("SdkSockJSServer Started on " + coreConfig().getValue("sdk_httpserver_host") + ":" + coreConfig().getValue("sdk_httpserver_port"));
        });
    }

    @Override
    public void stop() {
        httpServer.close(asyncResult -> {
            if (asyncResult.succeeded()) {
                logger.info("SdkSockJSServer Stopped");
            }
        });
    }

    @Override
    public String name() {
        return getClass().getCanonicalName();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy