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

hu.akarnokd.reactiverpc.RpcServer Maven / Gradle / Ivy

There is a newer version: 0.2.0
Show newest version
package hu.akarnokd.reactiverpc;

import java.io.IOException;
import java.net.*;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

import rsc.flow.Cancellation;
import rsc.scheduler.*;
import rsc.util.UnsignalledExceptions;

public final class RpcServer {
    
    final Object localAPI;
    final Class remoteAPI;

    static Scheduler scheduler = new ExecutorServiceScheduler(Executors.newCachedThreadPool(r -> {
        Thread t = new Thread(r, "akarnokd-reactive-rpc-clientpool");
        t.setDaemon(true);
        return t;
    }));

    
    private RpcServer(Object localAPI, Class remoteAPI) {
        this.localAPI = localAPI;
        this.remoteAPI = remoteAPI;
        
    }
    
    public static RpcServer createLocal(Object localAPI) {
        Objects.requireNonNull(localAPI, "localAPI");
        RpcServiceMapper.serverServiceMap(localAPI);
        return new RpcServer<>(localAPI, null);
    }
    
    public static  RpcServer createRemote(Class remoteAPI) {
        Objects.requireNonNull(remoteAPI, "remoteAPI");
        RpcServiceMapper.clientServiceMap(remoteAPI);
        return new RpcServer<>(null, remoteAPI);
    }
    
    public static  RpcServer createBidirectional(Object localAPI, Class remoteAPI) {
        Objects.requireNonNull(localAPI, "localAPI");
        RpcServiceMapper.serverServiceMap(localAPI);
        Objects.requireNonNull(remoteAPI, "remoteAPI");
        RpcServiceMapper.clientServiceMap(remoteAPI);
        return new RpcServer<>(localAPI, remoteAPI);
    }
    
    public AutoCloseable start(int port) {
        ServerSocket ssocket;
        try {
            ssocket = new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        
        return setup(ssocket);
    }
    
    AutoCloseable setup(ServerSocket ssocket) {
        Scheduler acceptor = new ParallelScheduler(1, "akarnokd-reactive-rpc-connection", true);

        AtomicBoolean done = new AtomicBoolean();
        Cancellation c = acceptor.schedule(() -> {
            socketAccept(ssocket, done);
        });
        
        return () -> {
            if (done.compareAndSet(false, true)) {
                c.dispose();
                ssocket.close();
            }
        };
    }
    
    void socketAccept(ServerSocket ssocket, AtomicBoolean done) {
        while (!Thread.currentThread().isInterrupted()) {
            Socket socket;
            
            try {
                socket = ssocket.accept();
                
            } catch (IOException e) {
                if (!done.get()) {
                    UnsignalledExceptions.onErrorDropped(e);
                }
                return;
            }
            
            try {
                RpcSocketManager.connect(socket, socket.getInetAddress(), socket.getPort(), 
                        remoteAPI, localAPI, c -> { }, scheduler, true);
            } catch (Throwable ex) {
                UnsignalledExceptions.onErrorDropped(ex);
                try {
                    socket.close();
                } catch (IOException e) {
                    UnsignalledExceptions.onErrorDropped(e);
                }
            }
        }
    }
    
    public AutoCloseable start(InetAddress localAddress, int port) {
        ServerSocket ssocket;
        try {
            ssocket = new ServerSocket(port, 50, localAddress);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        
        return setup(ssocket);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy